From 399b7dcbd9e650610183e4bba5c1c34c16713d9e Mon Sep 17 00:00:00 2001 From: Sven Robertz <sven@cs.lth.se> Date: Wed, 20 Feb 2013 17:15:43 +0100 Subject: [PATCH] packed lengths and numbers seem to work in C and Java --- compiler/C_CodeGen.jrag | 6 +- compiler/Signature.jrag | 28 +++++++-- examples/simple/example_decoder.c | 15 +++++ lib/c/experimental/pack.c | 17 +++--- lib/c/labcomm.c | 36 ++++++----- lib/c/labcomm_private.h | 61 ++++++++++++++++++- .../lth/control/labcomm/LabCommDecoder.java | 3 +- .../labcomm/LabCommDecoderChannel.java | 43 +++++++++---- .../lth/control/labcomm/LabCommEncoder.java | 3 +- .../labcomm/LabCommEncoderChannel.java | 32 ++++++++-- 10 files changed, 195 insertions(+), 49 deletions(-) diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag index caf57e9..1efc0a3 100644 --- a/compiler/C_CodeGen.jrag +++ b/compiler/C_CodeGen.jrag @@ -496,7 +496,8 @@ aspect C_Decoder { } public void VariableSize.C_emitDecoderDecodeLimit(C_env env, int i) { - env.println(env.qualid + ".n_" + i + " = labcomm_decode_int(d);"); + //env.println(env.qualid + ".n_" + i + " = labcomm_decode_int(d);"); + env.println(env.qualid + ".n_" + i + " = labcomm_decode_packed32(d);"); } public void ArrayType.C_emitDecoderDecodeLimit(C_env env) { @@ -721,7 +722,8 @@ aspect C_Encoder { } public void VariableSize.C_emitEncoderEncodeLimit(C_env env, int i) { - env.println("labcomm_encode_int(e, " + env.qualid + ".n_" + i + ");"); + //env.println("labcomm_encode_int(e, " + env.qualid + ".n_" + i + ");"); + env.println("labcomm_encode_packed32(e, " + env.qualid + ".n_" + i + ");"); } public void ArrayType.C_emitEncoderEncodeLimit(C_env env) { diff --git a/compiler/Signature.jrag b/compiler/Signature.jrag index fb65987..6d5f16e 100644 --- a/compiler/Signature.jrag +++ b/compiler/Signature.jrag @@ -38,11 +38,27 @@ aspect Signature { } public void addInt(int value, String comment) { - byte[] data = new byte[4]; - for (int i = 0 ; i < 4 ; i++) { - data[3 - i] = (byte)((value >> (8 * i)) & 0xff); - } - add(data, comment); + byte[] packed = new byte[5]; + +// System.out.println("addInt: "+value); + int tmp = value; + int len = 0; + + while( tmp >= 0x80 ) { + packed[len] = (byte) ((tmp & 0x7f) | 0x80 ) ; + tmp >>>= 7; + len++; + } + packed[len] = (byte) (tmp & 0x7f); +// System.out.println("packed: "+packed[len]+ "len = "+len); + + add(java.util.Arrays.copyOf(packed, len+1), comment); + +// byte[] data = new byte[4]; +// for (int i = 0 ; i < 4 ; i++) { +// data[3 - i] = (byte)((value >> (8 * i)) & 0xff); +// } +// add(data, comment); } public void addString(String value, String comment) { @@ -196,4 +212,4 @@ aspect Signature { return "_"; } -} \ No newline at end of file +} diff --git a/examples/simple/example_decoder.c b/examples/simple/example_decoder.c index bfe8430..9aa6b40 100644 --- a/examples/simple/example_decoder.c +++ b/examples/simple/example_decoder.c @@ -12,6 +12,20 @@ static void handle_simple_IntString(simple_IntString *v,void *context) { printf("Got IntString. x=%d, s=%s\n", v->x, v->s); } +static void handle_simple_TwoArrays(simple_TwoArrays *d,void *context) { + printf("Got TwoArrays:"); + int i; + for(i=0; i<2; i++) { + printf("%d ",d->fixed.a[i]); + } + printf("\n"); + for(i=0; i<d->variable.n_1; i++) { + printf("%d ",d->variable.a[0+2*i]); + printf("%d ",d->variable.a[1+2*i]); + } + printf("\n"); +} + int main(int argc, char *argv[]) { int fd; struct labcomm_decoder *decoder; @@ -29,6 +43,7 @@ int main(int argc, char *argv[]) { labcomm_decoder_register_simple_TwoInts(decoder, handle_simple_TwoInts, context); labcomm_decoder_register_simple_IntString(decoder, handle_simple_IntString, context); + labcomm_decoder_register_simple_TwoArrays(decoder, handle_simple_TwoArrays, context); printf("Decoding:\n"); labcomm_decoder_run(decoder); diff --git a/lib/c/experimental/pack.c b/lib/c/experimental/pack.c index 1860964..06636e3 100644 --- a/lib/c/experimental/pack.c +++ b/lib/c/experimental/pack.c @@ -1,11 +1,12 @@ #include <stdio.h> +typedef unsigned int number; -unsigned char do_pack(unsigned char *buf, unsigned long i) +unsigned char do_pack(unsigned char *buf, number i) { printf("do_pack %lu == %lx\n", i, i); - unsigned long tmp = i; + number tmp = i; unsigned char res = 0; while ( tmp >= 0x80 ) { @@ -17,14 +18,16 @@ unsigned char do_pack(unsigned char *buf, unsigned long i) return res+1; } -unsigned long do_unpack(unsigned char *buf) +number do_unpack(unsigned char *buf) { - unsigned long res=0; + number res=0; unsigned char i=0; unsigned char cont=1; do { - res |= (buf[i] & 0x7f) << 7*i; - cont = buf[i++] & 0x80; + unsigned char c = buf[i]; + res |= (c & 0x7f) << 7*i; + cont = c & 0x80; + i++; } while(cont); return res; @@ -65,7 +68,7 @@ int main() print_packed(buf, len); printf("... unpacks to %u\n\n", do_unpack(buf)); - len = do_pack(buf, 0xffffffffffffffff); + len = do_pack(buf, 0xffffffff); print_packed(buf, len); printf("... unpacks to %lx\n", do_unpack(buf)); diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c index 34ce50b..b67be7a 100644 --- a/lib/c/labcomm.c +++ b/lib/c/labcomm.c @@ -108,7 +108,7 @@ static void do_encoder_register(struct labcomm_encoder *e, context->sample = sample; e->writer.write(&e->writer, labcomm_writer_start); - labcomm_encode_int(e, signature->type); + labcomm_encode_packed32(e, signature->type); labcomm_encode_type_index(e, signature); labcomm_encode_string(e, signature->name); for (i = 0 ; i < signature->size ; i++) { @@ -204,7 +204,7 @@ void labcomm_encoder_free(labcomm_encoder_t* e) void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s) { int index = get_encoder_index(e, s); - labcomm_encode_int(e, index); + labcomm_encode_packed32(e, index); } static int signature_writer( @@ -249,27 +249,32 @@ static void collect_flat_signature( labcomm_decoder_t *decoder, labcomm_encoder_t *signature_writer) { - int type = labcomm_decode_int(decoder); + //int type = labcomm_decode_int(decoder); + int type = labcomm_decode_packed32(decoder); +// printf("%s: type=%x\n", __FUNCTION__, type); if (type >= LABCOMM_USER) { - printf("Implement %s ...\n", __FUNCTION__); + printf("Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type); } else { - labcomm_encode_int(signature_writer, type); + //labcomm_encode_int(signature_writer, type); + labcomm_encode_packed32(signature_writer, type); switch (type) { case LABCOMM_ARRAY: { int dimensions, i; - dimensions = labcomm_decode_int(decoder); - labcomm_encode_int(signature_writer, dimensions); + dimensions = labcomm_decode_packed32(decoder); //labcomm_decode_int(decoder); //unpack32 + labcomm_encode_packed32(signature_writer, dimensions); //pack32 for (i = 0 ; i < dimensions ; i++) { - int n = labcomm_decode_int(decoder); - labcomm_encode_int(signature_writer, n); + int n = labcomm_decode_packed32(decoder); //labcomm_decode_int(decoder); + labcomm_encode_packed32(signature_writer, n); // labcomm_encode_int(signature_writer, n); } collect_flat_signature(decoder, signature_writer); } break; case LABCOMM_STRUCT: { int fields, i; - fields = labcomm_decode_int(decoder); - labcomm_encode_int(signature_writer, fields); + //fields = labcomm_decode_int(decoder); + //labcomm_encode_int(signature_writer, fields); + fields = labcomm_decode_packed32(decoder); + labcomm_encode_packed32(signature_writer, fields); for (i = 0 ; i < fields ; i++) { char *name = labcomm_decode_string(decoder); labcomm_encode_string(signature_writer, name); @@ -287,7 +292,7 @@ static void collect_flat_signature( case LABCOMM_STRING: { } break; default: { - printf("Implement %s ...\n", __FUNCTION__); + printf("Implement %s (2) for type 0x%x...\n", __FUNCTION__, type); } break; } } @@ -326,7 +331,9 @@ static int do_decode_one(labcomm_decoder_t *d) if (result > 0) { labcomm_decoder_context_t *context = d->context; - result = labcomm_decode_int(d); +// printf("do_decode_one: result = %x\n", result); + result = labcomm_decode_packed32(d); +// printf("do_decode_one: result(2) = %x\n", result); if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) { labcomm_encoder_t *e = labcomm_encoder_new(signature_writer, 0); labcomm_signature_t signature; @@ -335,8 +342,9 @@ static int do_decode_one(labcomm_decoder_t *d) e->writer.write(&e->writer, labcomm_writer_start); signature.type = result; - index = labcomm_decode_int(d); + index = labcomm_decode_packed32(d); //int signature.name = labcomm_decode_string(d); +// printf("do_decode_one: result = %x, index = %x, name=%s\n", result, index, signature.name); collect_flat_signature(d, e); signature.size = e->writer.pos; signature.signature = e->writer.data; diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h index 3bc5140..3c4767b 100644 --- a/lib/c/labcomm_private.h +++ b/lib/c/labcomm_private.h @@ -109,12 +109,45 @@ LABCOMM_DECODE(int, int) LABCOMM_DECODE(long, long long) LABCOMM_DECODE(float, float) LABCOMM_DECODE(double, double) + +static inline unsigned int labcomm_unpack32(labcomm_reader_t *r) +{ + unsigned int res=0; + unsigned char i=0; + unsigned char cont=1; + do { + if (r->pos >= r->count) { + r->read(r, labcomm_reader_continue); + } +#ifdef IDIOTDEBUG + { + int k; + for(k=0; k<=r->pos; k++) printf("%2x\n", r->data[k]); + } +#endif + unsigned char c = r->data[r->pos]; + res |= (c & 0x7f) << 7*i; + cont = c & 0x80; +#ifdef IDIOTDEBUG + printf("unpack32: %x (%x, %d, %d)\n", res, c, i, cont); +#endif + i++; + r->pos++; + } while(cont); + return res; +} + +static inline unsigned int labcomm_decode_packed32(labcomm_decoder_t *d) +{ + return labcomm_unpack32(&d->reader); +} + static inline char *labcomm_read_string(labcomm_reader_t *r) { char *result; int length, i; - length = labcomm_read_int(r); + length = labcomm_unpack32(r); result = malloc(length + 1); for (i = 0 ; i < length ; i++) { if (r->pos >= r->count) { @@ -235,12 +268,36 @@ LABCOMM_ENCODE(int, int) LABCOMM_ENCODE(long, long long) LABCOMM_ENCODE(float, float) LABCOMM_ENCODE(double, double) + +static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data) +{ + unsigned int tmp, i; + + tmp = data; + + while (tmp >= 0x80) { + if (w->pos >= w->count) { + w->write(w, labcomm_writer_continue); + } + w->data[w->pos] = (tmp & 0x7f) | 0x80; + w->pos++; + tmp >>= 7; + } + w->data[w->pos] = tmp; + w->pos++; +} + +static inline void labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int data) +{ + labcomm_pack32(&e->writer, data); +} + static inline void labcomm_write_string(labcomm_writer_t *w, char *s) { int length, i; length = strlen((char*)s); - labcomm_write_int(w, length); + labcomm_pack32(w, length); for (i = 0 ; i < length ; i++) { if (w->pos >= w->count) { w->write(w, labcomm_writer_continue); diff --git a/lib/java/se/lth/control/labcomm/LabCommDecoder.java b/lib/java/se/lth/control/labcomm/LabCommDecoder.java index e8f6b8f..a40fb85 100644 --- a/lib/java/se/lth/control/labcomm/LabCommDecoder.java +++ b/lib/java/se/lth/control/labcomm/LabCommDecoder.java @@ -14,5 +14,6 @@ public interface LabCommDecoder { public float decodeFloat() throws IOException; public double decodeDouble() throws IOException; public String decodeString() throws IOException; + public int decodePacked32() throws IOException; -} \ No newline at end of file +} diff --git a/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java b/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java index 4096d47..034d31b 100644 --- a/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java +++ b/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java @@ -18,11 +18,11 @@ public class LabCommDecoderChannel implements LabCommDecoder { public void runOne() throws Exception { boolean done = false; while (!done) { - int tag = decodeInt(); + int tag = decodePacked32(); switch (tag) { case LabComm.TYPEDEF: case LabComm.SAMPLE: { - int index = decodeInt(); + int index = decodePacked32(); String name = decodeString(); ByteArrayOutputStream signature = new ByteArrayOutputStream(); collectFlatSignature(new LabCommEncoderChannel(signature)); @@ -55,20 +55,20 @@ public class LabCommDecoderChannel implements LabCommDecoder { } private void collectFlatSignature(LabCommEncoder out) throws IOException { - int type = decodeInt(); - out.encodeInt(type); + int type = decodePacked32(); + out.encodePacked32(type); switch (type) { case LabComm.ARRAY: { - int dimensions = decodeInt(); - out.encodeInt(dimensions); + int dimensions = decodePacked32(); + out.encodePacked32(dimensions); for (int i = 0 ; i < dimensions ; i++) { - out.encodeInt(decodeInt()); + out.encodePacked32(decodePacked32()); } collectFlatSignature(out); } break; case LabComm.STRUCT: { - int fields = decodeInt(); - out.encodeInt(fields); + int fields = decodePacked32(); + out.encodePacked32(fields); for (int i = 0 ; i < fields ; i++) { out.encodeString(decodeString()); collectFlatSignature(out); @@ -124,9 +124,30 @@ public class LabCommDecoderChannel implements LabCommDecoder { } public String decodeString() throws IOException { - in.readShort(); // HACK - return in.readUTF(); + //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 |= (c & 0x7f) << 7*i; + cont = (c & 0x80) != 0; + System.out.println("decodePacked32: "+res); + i++; + } while(cont); + + return (int) (res & 0xffffffff); + } } diff --git a/lib/java/se/lth/control/labcomm/LabCommEncoder.java b/lib/java/se/lth/control/labcomm/LabCommEncoder.java index 66584db..f332d78 100644 --- a/lib/java/se/lth/control/labcomm/LabCommEncoder.java +++ b/lib/java/se/lth/control/labcomm/LabCommEncoder.java @@ -15,5 +15,6 @@ public interface LabCommEncoder { 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; -} \ No newline at end of file +} diff --git a/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java b/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java index b339c9f..cbb4bd7 100644 --- a/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java +++ b/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java @@ -21,8 +21,8 @@ public class LabCommEncoderChannel implements LabCommEncoder { public void register(LabCommDispatcher dispatcher) throws IOException { int index = registry.add(dispatcher); - encodeInt(LabComm.SAMPLE); - encodeInt(index); + encodePacked32(LabComm.SAMPLE); + encodePacked32(index); encodeString(dispatcher.getName()); byte[] signature = dispatcher.getSignature(); for (int i = 0 ; i < signature.length ; i++) { @@ -32,7 +32,7 @@ public class LabCommEncoderChannel implements LabCommEncoder { } public void begin(Class<? extends LabCommSample> c) throws IOException { - encodeInt(registry.getTag(c)); + encodePacked32(registry.getTag(c)); } public void end(Class<? extends LabCommSample> c) throws IOException { @@ -70,9 +70,31 @@ public class LabCommEncoderChannel implements LabCommEncoder { } public void encodeString(String value) throws IOException { - data.writeShort(0); // HACK... - data.writeUTF(value); + //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]); + } } + public void encodePacked32(long value) throws IOException { + long tmp = value; + + while( tmp >= 0x80 ) { + encodeByte( (byte) ((tmp & 0x7f) | 0x80 ) ); + tmp >>>= 7; + } + encodeByte( (byte) (tmp & 0x7f) ); + } } -- GitLab