Commit 36839bac authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Changed encoding of packed32 to be coded big endian with use of

continuation bit. C# is currently (intentionally) broken. 
Java and Python are untested.
parent 274eddf0
......@@ -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) {
......
......@@ -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);
......
......@@ -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)
......
......@@ -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");
......
......@@ -163,6 +163,7 @@ namespace se.lth.control.labcomm {
}
public int decodePacked32() {
TODO: Correct byteorder
Int64 res = 0;
byte i = 0;
bool cont = true;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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) );
}
}
......@@ -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()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment