From 36839bacaa019cb7a63b0e48393ae20a6d7dbb14 Mon Sep 17 00:00:00 2001 From: Anders Blomdell <anders.blomdell@control.lth.se> Date: Tue, 30 Apr 2013 13:43:46 +0200 Subject: [PATCH] Changed encoding of packed32 to be coded big endian with use of continuation bit. C# is currently (intentionally) broken. Java and Python are untested. --- compiler/Signature.jrag | 33 ++++------- lib/c/experimental/labcomm_sig_parser.c | 7 ++- lib/c/labcomm_private.h | 57 +++++++++++++++++-- lib/c/test/test_labcomm_basic_type_encoding.c | 23 ++++---- .../control/labcomm/LabCommDecoderChannel.cs | 1 + .../control/labcomm/LabCommEncoderChannel.cs | 2 +- .../labcomm/LabCommDecoderChannel.java | 2 +- .../labcomm/LabCommEncoderChannel.java | 13 +++-- lib/python/labcomm/LabComm.py | 40 +++++++------ 9 files changed, 110 insertions(+), 68 deletions(-) diff --git a/compiler/Signature.jrag b/compiler/Signature.jrag index 6d5f16e..d329629 100644 --- a/compiler/Signature.jrag +++ b/compiler/Signature.jrag @@ -38,27 +38,18 @@ aspect Signature { } public void addInt(int value, String 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); + byte[] tmp = new byte[5]; + long v = value & 0xffffffff; + int i, j; + + for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) { + tmp[i] = (byte)(v & 0x7f); + } + byte[] packed = new byte[i]; + for (i = i - 1, j = 0 ; i >= 0 ; i--, j++) { + packed[j] = (byte)(tmp[i] | (i!=0?0x80:0x00)); + } + add(packed, comment); } public void addString(String value, String comment) { diff --git a/lib/c/experimental/labcomm_sig_parser.c b/lib/c/experimental/labcomm_sig_parser.c index bfe9f1b..23e3758 100644 --- a/lib/c/experimental/labcomm_sig_parser.c +++ b/lib/c/experimental/labcomm_sig_parser.c @@ -57,14 +57,17 @@ static inline unsigned int get32(labcomm_sig_parser_t *b) { /* aux method for reading labcomm varint from a char* size is an out parameter: if not NULL the number of bytes read will be written here */ -static int unpack_varint(unsigned char *buf, unsigned int idx, unsigned char *size) { +static unsigned int unpack_varint(unsigned char *buf, + unsigned int idx, + unsigned char *size) +{ unsigned int res = 0; unsigned int i=0; unsigned char cont = TRUE; do { unsigned char c = buf[idx+i]; - res |= (c & 0x7f) << 7*i; + res = (res << 7) | (c & 0x7f); cont = c & 0x80; i++; } while(cont); diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h index 13761dd..e75a064 100644 --- a/lib/c/labcomm_private.h +++ b/lib/c/labcomm_private.h @@ -124,6 +124,7 @@ LABCOMM_DECODE(long, long long) LABCOMM_DECODE(float, float) LABCOMM_DECODE(double, double) +#if 0 /* * Unpack a 32 bit unsigned number from a sequence bytes, where the * first byte is prefixed with a variable length bit pattern that @@ -136,7 +137,7 @@ LABCOMM_DECODE(double, double) * 0b1110 - 4 bytes (0x00200000 - 0x0fffffff) * 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused] */ -static inline unsigned int labcomm_unpack32(labcomm_reader_t *r) +static inline unsigned int labcomm_read_unpacked32(labcomm_reader_t *r) { unsigned int result = 0; int n, i; @@ -171,10 +172,31 @@ static inline unsigned int labcomm_unpack32(labcomm_reader_t *r) } return result; } +#endif +static inline unsigned int labcomm_read_unpacked32(labcomm_reader_t *r) +{ + unsigned int result = 0; + + while (1) { + unsigned char tmp; + + if (r->pos >= r->count) { + r->read(r, labcomm_reader_continue); + } + tmp = r->data[r->pos]; + r->pos++; + result = (result << 7) | (tmp & 0x7f); + if ((tmp & 0x80) == 0) { + break; + } + } + return result; +} + static inline unsigned int labcomm_decode_packed32(labcomm_decoder_t *d) { - return labcomm_unpack32(&d->reader); + return labcomm_read_unpacked32(&d->reader); } static inline char *labcomm_read_string(labcomm_reader_t *r) @@ -182,7 +204,7 @@ static inline char *labcomm_read_string(labcomm_reader_t *r) char *result; int length, i; - length = labcomm_unpack32(r); + length = labcomm_read_unpacked32(r); result = malloc(length + 1); for (i = 0 ; i < length ; i++) { if (r->pos >= r->count) { @@ -248,7 +270,7 @@ int labcomm_internal_encode( return 0; \ } \ static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ - return labcomm_write_##name(&e->writer, data); \ + return labcomm_write_##name(&e->writer, data); \ } #else @@ -268,7 +290,7 @@ int labcomm_internal_encode( return 0; \ } \ static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ - return labcomm_write_##name(&e->writer, data); \ + return labcomm_write_##name(&e->writer, data); \ } #endif @@ -281,6 +303,7 @@ LABCOMM_ENCODE(long, long long) LABCOMM_ENCODE(float, float) LABCOMM_ENCODE(double, double) +#if 0 /* * Pack the 32 bit unsigned number data as a sequence bytes, where the * first byte is prefixed with a variable length bit pattern that @@ -294,7 +317,7 @@ LABCOMM_ENCODE(double, double) * 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused] */ static inline int labcomm_write_packed32(labcomm_writer_t *w, - unsigned int data) + unsigned int data) { int n; unsigned char tag; @@ -367,6 +390,28 @@ static inline int labcomm_write_packed32(labcomm_writer_t *w, } return 0; } +#endif + +static inline int labcomm_write_packed32(labcomm_writer_t *w, + unsigned int data) +{ + unsigned char tmp[5]; + int i; + + for (i = 0 ; i == 0 || data ; i++, data = (data >> 7)) { + tmp[i] = data & 0x7f; + } + for (i = i - 1 ; i >= 0 ; i--) { + if (w->pos >= w->count) { + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } + } + w->data[w->pos++] = tmp[i] | (i?0x80:0x00); + } + return 0; +} + static inline int labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int data) diff --git a/lib/c/test/test_labcomm_basic_type_encoding.c b/lib/c/test/test_labcomm_basic_type_encoding.c index c8dfff7..270796e 100644 --- a/lib/c/test/test_labcomm_basic_type_encoding.c +++ b/lib/c/test/test_labcomm_basic_type_encoding.c @@ -2,6 +2,7 @@ #include <string.h> #include "labcomm_private.h" +static int line; int test_write(struct labcomm_writer *w, labcomm_writer_action_t a, ...) { @@ -11,7 +12,7 @@ int test_write(struct labcomm_writer *w, labcomm_writer_action_t a, ...) int test_read(struct labcomm_reader *r, labcomm_reader_action_t a, ...) { - fprintf(stderr, "test_read should not be called\n"); + fprintf(stderr, "test_read should not be called %s:%d\n", __FILE__, line); exit(1); } @@ -57,9 +58,10 @@ typedef unsigned char byte; #define TEST_WRITE_READ(type, format, value, expect_count, expect_bytes) \ { \ type decoded; \ + line = __LINE__; \ encoder.writer.pos = 0; \ labcomm_encode_##type(&encoder, value); \ - writer_assert(#type, __LINE__, expect_count, (uint8_t*)expect_bytes); \ + writer_assert(#type, expect_count, (uint8_t*)expect_bytes); \ decoder.reader.count = encoder.writer.pos; \ decoder.reader.pos = 0; \ decoded = labcomm_decode_##type(&decoder); \ @@ -71,7 +73,6 @@ typedef unsigned char byte; } static void writer_assert(char *type, - int line, int count, uint8_t *bytes) { @@ -101,14 +102,14 @@ int main(void) { TEST_WRITE_READ(packed32, "%d", 0x0, 1, "\x00"); TEST_WRITE_READ(packed32, "%d", 0x7f, 1, "\x7f"); - TEST_WRITE_READ(packed32, "%d", 0x80, 2, "\x80\x80"); - TEST_WRITE_READ(packed32, "%d", 0x3fff, 2, "\xbf\xff"); - TEST_WRITE_READ(packed32, "%d", 0x4000, 3, "\xc0\x40\x00"); - TEST_WRITE_READ(packed32, "%d", 0x1fffff, 3, "\xdf\xff\xff"); - TEST_WRITE_READ(packed32, "%d", 0x200000, 4, "\xe0\x20\x00\x00"); - TEST_WRITE_READ(packed32, "%d", 0xfffffff, 4, "\xef\xff\xff\xff"); - TEST_WRITE_READ(packed32, "%d", 0x10000000, 5, "\xf0\x10\x00\x00\x00"); - TEST_WRITE_READ(packed32, "%d", 0xffffffff, 5, "\xf0\xff\xff\xff\xff"); + TEST_WRITE_READ(packed32, "%d", 0x80, 2, "\x81\x00"); + TEST_WRITE_READ(packed32, "%d", 0x3fff, 2, "\xff\x7f"); + TEST_WRITE_READ(packed32, "%d", 0x4000, 3, "\x81\x80\x00"); + TEST_WRITE_READ(packed32, "%d", 0x1fffff, 3, "\xff\xff\x7f"); + TEST_WRITE_READ(packed32, "%d", 0x200000, 4, "\x81\x80\x80\x00"); + TEST_WRITE_READ(packed32, "%d", 0xfffffff, 4, "\xff\xff\xff\x7f"); + TEST_WRITE_READ(packed32, "%d", 0x10000000, 5, "\x81\x80\x80\x80\x00"); + TEST_WRITE_READ(packed32, "%d", 0xffffffff, 5, "\x8f\xff\xff\xff\x7f"); TEST_WRITE_READ(boolean, "%d", 0, 1, "\x00"); TEST_WRITE_READ(boolean, "%d", 1, 1, "\x01"); TEST_WRITE_READ(byte, "%d", 0, 1, "\x00"); diff --git a/lib/csharp/se/lth/control/labcomm/LabCommDecoderChannel.cs b/lib/csharp/se/lth/control/labcomm/LabCommDecoderChannel.cs index 08b365c..aec8b0a 100644 --- a/lib/csharp/se/lth/control/labcomm/LabCommDecoderChannel.cs +++ b/lib/csharp/se/lth/control/labcomm/LabCommDecoderChannel.cs @@ -163,6 +163,7 @@ namespace se.lth.control.labcomm { } public int decodePacked32() { + TODO: Correct byteorder Int64 res = 0; byte i = 0; bool cont = true; diff --git a/lib/csharp/se/lth/control/labcomm/LabCommEncoderChannel.cs b/lib/csharp/se/lth/control/labcomm/LabCommEncoderChannel.cs index 73ee904..62d72f0 100644 --- a/lib/csharp/se/lth/control/labcomm/LabCommEncoderChannel.cs +++ b/lib/csharp/se/lth/control/labcomm/LabCommEncoderChannel.cs @@ -90,7 +90,7 @@ namespace se.lth.control.labcomm { public void encodePacked32(Int64 value) { Int64 tmp = value; - + TODO: Correct byteorder while(tmp >= 0x80) { encodeByte( (byte) ((tmp & 0x7f) | 0x80 ) ); tmp >>= 7; diff --git a/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java b/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java index d783bd3..c3f6984 100644 --- a/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java +++ b/lib/java/se/lth/control/labcomm/LabCommDecoderChannel.java @@ -141,7 +141,7 @@ public class LabCommDecoderChannel implements LabCommDecoder { do { byte c = in.readByte(); - res |= (c & 0x7f) << 7*i; + res = (res << 7) | (c & 0x7f); cont = (c & 0x80) != 0; i++; } while(cont); diff --git a/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java b/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java index 4154ca0..204f6cc 100644 --- a/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java +++ b/lib/java/se/lth/control/labcomm/LabCommEncoderChannel.java @@ -94,13 +94,16 @@ public class LabCommEncoderChannel implements LabCommEncoder { } public void encodePacked32(long value) throws IOException { - long tmp = value; + byte[] tmp = new byte[5]; + long v = value & 0xffffffff; + int i; - while( tmp >= 0x80 ) { - encodeByte( (byte) ((tmp & 0x7f) | 0x80 ) ); - tmp >>>= 7; + for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) { + tmp[i] = (byte)(v & 0x7f); + } + for (i = i - 1 ; i >= 0 ; i--) { + encodeByte((byte)(tmp[i] | (i!=0?0x80:0x00))); } - encodeByte( (byte) (tmp & 0x7f) ); } } diff --git a/lib/python/labcomm/LabComm.py b/lib/python/labcomm/LabComm.py index 1dfc4e0..a6ede79 100644 --- a/lib/python/labcomm/LabComm.py +++ b/lib/python/labcomm/LabComm.py @@ -89,13 +89,10 @@ #?? +----+----+----+----+ # # -# type numbers and lengths do not have a fixed lenght, but are packed into sequences -# of 7 bit chunks, represented in bytes with the high bit meaning that more data -# is to come. -# -# The chunks are sent "little endian": each 7 bit chunk is more significant than -# the previous. See encode_packed32 and decode_packed32 in in Codec classes below. - +# type numbers and lengths do not have a fixed lenght, but are packed into +# sequences of 7 bit chunks, represented in bytes with the high bit meaning +# that more data is to come. + import struct as packer i_TYPEDEF = 0x01 @@ -580,12 +577,14 @@ class Encoder(Codec): decl.encode_decl(self) def encode_packed32(self, v): - tmp = v & 0xffffffff; - - while(tmp >= 0x80 ): - self.encode_byte( (tmp & 0x7f) | 0x80 ) - tmp >>= 7 - self.encode_byte(tmp & 0x7f) + v = v & 0xffffffff + tmp = [ v & 0x7f ] + v = v >> 7 + while v: + tmp.append(v & 0x7f | 0x80) + v = v >> 7 + for c in reversed(tmp): + self.encode_byte(c) def encode_type(self, index): self.encode_packed32(index) @@ -666,14 +665,13 @@ class Decoder(Codec): return result def decode_packed32(self): - res = 0 - i = 0 - cont = True - while (cont): - c = self.decode_byte() - res |= (c & 0x7f) << 7*i - cont = (c & 0x80) != 0; - return res + result = 0 + while True: + tmp = self.decode_byte() + result = (result << 7) | (tmp & 0x7f) + if (tmp & 0x80) == 0: + break + return result def decode_type_number(self): return self.decode_packed32() -- GitLab