From 177c67030b9e90edc272ed5e3b9bb38b1f7be9c3 Mon Sep 17 00:00:00 2001
From: Sven Gestegard Robertz <sven.robertz@cs.lth.se>
Date: Mon, 10 Nov 2014 14:24:14 +0100
Subject: [PATCH] minor preliminary refactoring/bringover from old branch

---
 lib/c/labcomm_decoder.c                       | 131 +++++++++++++-----
 lib/java/se/lth/control/labcomm/Constant.java |   4 +-
 .../lth/control/labcomm/DecoderChannel.java   |  56 ++++++--
 .../lth/control/labcomm/EncoderChannel.java   |   2 +-
 lib/python/labcomm/LabComm.py                 |  61 ++++++--
 5 files changed, 196 insertions(+), 58 deletions(-)

diff --git a/lib/c/labcomm_decoder.c b/lib/c/labcomm_decoder.c
index 8a3e1ba..0aa1de9 100644
--- a/lib/c/labcomm_decoder.c
+++ b/lib/c/labcomm_decoder.c
@@ -190,6 +190,96 @@ static void reader_alloc(struct labcomm_decoder *d)
   }
 }
 
+static int decoder_skip(struct labcomm_decoder *d, int len, int tag)
+{
+  int i;
+  printf("got tag 0x%x, skipping %d bytes\n", tag, len);
+  for(i = 0; i <len; i++){
+    labcomm_read_byte(d->reader);
+    if (d->reader->error < 0) {
+      return d->reader->error;
+    }
+  }
+  return tag;
+}
+/* d        - decoder to read from
+   registry - decoder to lookup signatures (registry != d only if
+                nesting decoders, e.g., when decoding pragma)
+   len      - length of the labcomm packet )
+*/
+static int decode_pragma(struct labcomm_decoder *d,
+		         struct labcomm_decoder *registry,
+		         int len)
+{
+  char *pragma_type;
+  int result;
+  pragma_type = labcomm_read_string(d->reader);
+  if (d->reader->error < 0) {
+    result = d->reader->error;
+    goto out;
+  }
+  int bytes = labcomm_size_string(pragma_type);
+  int psize = len-bytes;
+  result = decoder_skip(d, psize, LABCOMM_PRAGMA);
+out:
+  return result;
+}
+
+static labcomm_decoder_function lookup_h(struct labcomm_decoder *d,
+		                         struct call_handler_context *wrap,
+		                         int remote_index,
+					 int **local_index)
+{
+  labcomm_decoder_function do_decode = NULL;
+  labcomm_scheduler_data_lock(d->scheduler);
+  *local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+      				      d->remote_to_local, int,
+      				      remote_index);
+  if (**local_index != 0) {
+    struct sample_entry *entry;
+
+    entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+      				  d->local, struct sample_entry,
+      				  **local_index);
+    wrap->local_index = **local_index;
+    wrap->signature = entry->signature;
+    wrap->handler = entry->handler;
+    wrap->context = entry->context;
+    do_decode = entry->decode;
+  }
+  labcomm_scheduler_data_unlock(d->scheduler);
+  return do_decode;
+}
+/* d            - decoder to read from
+   registry     - decoder to lookup signatures (registry != d only if
+                    nesting decoders, e.g., when decoding pragma)
+   remote_index -  received type index )
+*/
+static int decode_and_handle(struct labcomm_decoder *d,
+		             struct labcomm_decoder *registry,
+		             int remote_index)
+{
+  int result;
+  int *local_index;
+  struct call_handler_context wrap = {
+    .reader = d->reader,
+    .remote_index = remote_index,
+    .signature = NULL,
+    .handler = NULL,
+    .context = NULL,
+  };
+  labcomm_decoder_function do_decode = lookup_h(registry, &wrap, remote_index, &local_index);
+  result = *local_index;
+  if (do_decode) {
+    do_decode(d->reader, call_handler, &wrap);
+    if (d->reader->error < 0) {
+      result = d->reader->error;
+    }
+  } else {
+    result = -ENOENT;
+  }
+  return result;
+}
 int labcomm_decoder_decode_one(struct labcomm_decoder *d)
 {
   int result, remote_index, length;
@@ -223,48 +313,13 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
     result = -ECONNRESET;
   } else if (remote_index == LABCOMM_SAMPLE) {
     result = decode_sample(d, remote_index); 
-  } else if (remote_index == LABCOMM_PRAGMA && 0 /* d->pragma_handler*/) {
-    /* d->prama_handler(...); */
+  } else if (remote_index == LABCOMM_PRAGMA) {
+    result = decode_pragma(d, d, length);
   } else if (remote_index < LABCOMM_USER) {
     fprintf(stderr, "SKIP %d %d\n", remote_index, length);
     result = remote_index;
   } else {
-    int *local_index;
-    struct call_handler_context wrap = {
-      .reader = d->reader,
-      .remote_index = remote_index,
-      .signature = NULL,
-      .handler = NULL,
-      .context = NULL,
-    };
-    labcomm_decoder_function do_decode = NULL;
-
-    labcomm_scheduler_data_lock(d->scheduler);
-    local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
-					      d->remote_to_local, int,
-					      remote_index);
-    if (*local_index != 0) {
-      struct sample_entry *entry;
-
-      entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
-					  d->local, struct sample_entry,
-					  *local_index);
-      wrap.local_index = *local_index;
-      wrap.signature = entry->signature;
-      wrap.handler = entry->handler;
-      wrap.context = entry->context;
-      do_decode = entry->decode;
-      result = *local_index;
-    }
-    labcomm_scheduler_data_unlock(d->scheduler);
-    if (do_decode) {
-      do_decode(d->reader, call_handler, &wrap);
-      if (d->reader->error < 0) {
-	result = d->reader->error;
-      }
-    } else {
-      result = -ENOENT;
-    }
+    result = decode_and_handle(d, d, remote_index);
   }
 out:   
   return result;
diff --git a/lib/java/se/lth/control/labcomm/Constant.java b/lib/java/se/lth/control/labcomm/Constant.java
index 194ae8d..c5a580a 100644
--- a/lib/java/se/lth/control/labcomm/Constant.java
+++ b/lib/java/se/lth/control/labcomm/Constant.java
@@ -11,7 +11,9 @@ public class Constant {
    * Predeclared aggregate type indices
    */
   public static final int VERSION          = 0x01;
-  public static final int SAMPLE           = 0x02;
+  public static final int SAMPLE_DEF       = 0x02;
+  public static final int TYPE_DEF         = 0x03;
+  public static final int TYPE_BINDING     = 0x04;
   public static final int PRAGMA           = 0x3f;
   public static final int FIRST_USER_INDEX = 0x40; /* ..0xffffffff */
 
diff --git a/lib/java/se/lth/control/labcomm/DecoderChannel.java b/lib/java/se/lth/control/labcomm/DecoderChannel.java
index 6f7760f..c8d6925 100644
--- a/lib/java/se/lth/control/labcomm/DecoderChannel.java
+++ b/lib/java/se/lth/control/labcomm/DecoderChannel.java
@@ -11,9 +11,43 @@ public class DecoderChannel implements Decoder {
   private DataInputStream in;
   private DecoderRegistry registry;
 
-  public DecoderChannel(InputStream in) throws IOException {
+  private DecoderChannel(InputStream in, DecoderRegistry reg) throws IOException {
     this.in = new DataInputStream(in);
-    registry = new DecoderRegistry();
+    registry = reg;
+  }
+  public DecoderChannel(InputStream in) throws IOException {
+    this(in, new DecoderRegistry());
+  }
+
+  private void processSampleDef() throws IOException {
+    int index = decodePacked32();
+    String name = decodeString();
+    int signature_length = decodePacked32();
+    byte[] signature = new byte[signature_length];
+    ReadBytes(signature, signature_length);
+    registry.add(index, name, signature);
+  }	   
+
+
+  private void processTypeDef(int len) throws IOException {
+       System.out.println("Got TypeDef: skipping "+len+" bytes"); 
+       for(int i=0; i<len; i++) {
+           decodeByte();		  
+       }
+  }
+
+  private void processTypeBinding(int len) throws IOException {
+       System.out.println("Got TypeBinding: skipping "+len+" bytes"); 
+       for(int i=0; i<len; i++) {
+           decodeByte();		  
+       }
+  }
+
+  private void processPragma(int len) throws IOException {
+       System.out.println("Got Pragma: skipping "+len+" bytes"); 
+       for(int i=0; i<len; i++) {
+           decodeByte();		  
+       }
   }
 
   public void runOne() throws Exception {
@@ -29,13 +63,17 @@ public class DecoderChannel implements Decoder {
 			          version + " != " + Constant.CURRENT_VERSION);
           }
         } break;
-	case Constant.SAMPLE: {
-	  int index = decodePacked32();
-	  String name = decodeString();
-          int signature_length = decodePacked32();
-          byte[] signature = new byte[signature_length];
-          ReadBytes(signature, signature_length);
-	  registry.add(index, name, signature);
+	case Constant.SAMPLE_DEF: {
+          processSampleDef();
+	} break;
+	case Constant.TYPE_DEF: {
+          processTypeDef(length);
+	} break;
+	case Constant.TYPE_BINDING: {
+          processTypeBinding(length);
+	} break;
+	case Constant.PRAGMA: {
+          processPragma(length);
 	} break;
 	default: {
 	  DecoderRegistry.Entry e = registry.get(tag);
diff --git a/lib/java/se/lth/control/labcomm/EncoderChannel.java b/lib/java/se/lth/control/labcomm/EncoderChannel.java
index e7c3e80..08ef0fc 100644
--- a/lib/java/se/lth/control/labcomm/EncoderChannel.java
+++ b/lib/java/se/lth/control/labcomm/EncoderChannel.java
@@ -30,7 +30,7 @@ public class EncoderChannel implements Encoder {
 
   public void register(SampleDispatcher dispatcher) throws IOException {
     int index = registry.add(dispatcher);
-    begin(Constant.SAMPLE);
+    begin(Constant.SAMPLE_DEF);
     encodePacked32(index);
     encodeString(dispatcher.getName());
     byte[] signature = dispatcher.getSignature();
diff --git a/lib/python/labcomm/LabComm.py b/lib/python/labcomm/LabComm.py
index 9f854ec..dff29ce 100644
--- a/lib/python/labcomm/LabComm.py
+++ b/lib/python/labcomm/LabComm.py
@@ -11,7 +11,7 @@
 #   | ...
 #   +----+--
 #
-# LabComm22014 SAMPLE:
+# LabComm2014 SAMPLE_DEF:
 #
 #   +----+----+----+----+
 #   | id = 0x02             (packed32)
@@ -29,6 +29,37 @@
 #   | ...
 #   +----+--
 #
+# LabComm2014 TYPE_DEF: (as SAMPLE_DEF, but signatures are hierarchical,
+#                         i.e., may contain references to other types
+#
+#   +----+----+----+----+
+#   | id = 0x03             (packed32)
+#   +----+----+----+----+
+#   | length                (packed32)
+#   +----+----+----+----+
+#   | type number           (packed32)
+#   +----+----+----+----+
+#   | type name (UTF8)
+#   | ...
+#   +----+----+----+----+
+#   | signature length      (packed32)
+#   +----+----+----+----+
+#   | type signature
+#   | ...
+#   +----+--
+#
+# LabComm2014 TYPE_BINDING
+#
+#   +----+----+----+----+
+#   | id = 0x04             (packed32)
+#   +----+----+----+----+
+#   | length                (packed32)
+#   +----+----+----+----+
+#   | sample number         (packed32)
+#   +----+----+----+----+
+#   | type number           (packed32)
+#   +----+----+----+----+
+#
 # LabComm2014 User data:
 #
 #   +----+----+----+----+
@@ -123,10 +154,12 @@ import struct as packer
 DEFAULT_VERSION = "LabComm2014"
 
 # Allowed packet tags
-i_VERSION = 0x01
-i_SAMPLE  = 0x02
-i_PRAGMA  = 0x3f
-i_USER    = 0x40 # ..0xffffffff
+i_VERSION     = 0x01
+i_SAMPLE_DEF  = 0x02
+i_TYPE_DEF    = 0x03
+i_TYPE_BINDING= 0x04
+i_PRAGMA      = 0x3f
+i_USER        = 0x40 # ..0xffffffff
 
 # Predefined types
 i_ARRAY   = 0x10
@@ -310,7 +343,7 @@ class sample(object):
         self.decl = decl
 
     def encode_decl(self, encoder):
-        encoder.encode_type(i_SAMPLE)
+        encoder.encode_type(i_SAMPLE_DEF)
         with length_encoder(encoder) as e1:
             e1.encode_type(encoder.decl_to_index[self])
             e1.encode_string(self.name)
@@ -512,7 +545,7 @@ class struct:
         result += "\n])"
         return result
 
-SAMPLE = sample(None, None)
+SAMPLE_DEF = sample(None, None)
 
 ARRAY = array(None, None)
 STRUCT = struct({})
@@ -541,7 +574,7 @@ class Codec(object):
         self.predefined_types()
 
     def predefined_types(self):
-        self.add_decl(SAMPLE, i_SAMPLE)
+        self.add_decl(SAMPLE_DEF, i_SAMPLE_DEF)
 
         self.add_decl(ARRAY, i_ARRAY)
         self.add_decl(STRUCT, i_STRUCT)
@@ -693,6 +726,10 @@ class Decoder(Codec):
             raise Exception('Should not be used')
         return result
 
+    def skip(self, length):
+        for _ in xrange(length):
+            self.decode_byte()
+
     def decode(self):
         while True:
             index = self.decode_type_number()
@@ -705,9 +742,15 @@ class Decoder(Codec):
                 if self.version != other_version:
                     raise Exception("LabComm version mismatch %s != %s" %
                                     (version, other_version))
-        if index == i_SAMPLE:
+        if index == i_SAMPLE_DEF:
             decl = self.index_to_decl[index].decode_decl(self)
             value = None
+        elif index == i_TYPE_DEF:
+            print "Got type_def, skipping %d bytes" % length
+            self.skip(length)
+        elif index == i_TYPE_BINDING:
+            print "Got type_binding, skipping %d bytes" % length
+            self.skip(length)
         else:
             decl = self.index_to_decl[index]
             value = decl.decode(self)
-- 
GitLab