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