From 2d23900bc82acb810449c5f4ffdd072f55c0a6c1 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Wed, 24 Apr 2013 16:49:51 +0200
Subject: [PATCH] Some refactorings and initial try at O(1) lookup of encoder
 indices (linker magic provided).

---
 compiler/C_CodeGen.jrag                       |  4 +-
 lib/c/Makefile                                | 12 ++--
 lib/c/labcomm.c                               | 35 ++++++++---
 lib/c/labcomm.h                               | 24 +++-----
 lib/c/labcomm.linkscript                      |  8 +++
 lib/c/labcomm_dynamic_buffer_writer.c         |  2 +
 ...fd_reader_writer.c => labcomm_fd_reader.c} | 61 +++++--------------
 lib/c/labcomm_fd_reader.h                     | 12 ++++
 lib/c/labcomm_fd_reader_writer.h              | 16 -----
 lib/c/labcomm_fd_writer.c                     | 61 +++++++++++++++++++
 lib/c/labcomm_fd_writer.h                     | 12 ++++
 lib/c/labcomm_private.h                       | 34 ++---------
 lib/c/test/labcomm_mem_reader.c               |  6 +-
 lib/c/test/labcomm_mem_reader.h               |  4 +-
 lib/c/test/labcomm_mem_writer.c               |  1 +
 lib/c/test/test_labcomm.c                     |  1 +
 ...e.c => test_labcomm_basic_type_encoding.c} |  7 ++-
 17 files changed, 171 insertions(+), 129 deletions(-)
 create mode 100644 lib/c/labcomm.linkscript
 rename lib/c/{labcomm_fd_reader_writer.c => labcomm_fd_reader.c} (52%)
 create mode 100644 lib/c/labcomm_fd_reader.h
 delete mode 100644 lib/c/labcomm_fd_reader_writer.h
 create mode 100644 lib/c/labcomm_fd_writer.c
 create mode 100644 lib/c/labcomm_fd_writer.h
 rename lib/c/test/{test_labcomm_private.c => test_labcomm_basic_type_encoding.c} (97%)

diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag
index d445088..f79bbfc 100644
--- a/compiler/C_CodeGen.jrag
+++ b/compiler/C_CodeGen.jrag
@@ -803,8 +803,8 @@ aspect C_Signature {
       }
     }
     env.println("};");
-    env.println("labcomm_signature_t labcomm_signature_" + 
-		env.prefix + getName() + " = {");
+    env.println("LABCOMM_DECLARE_SIGNATURE(labcomm_signature_" + 
+		env.prefix + getName() + ") = {");
     env.indent();
     env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
     env.println("(int (*)(labcomm_signature_t *, void *))labcomm_sizeof_" + 
diff --git a/lib/c/Makefile b/lib/c/Makefile
index dd08db0..f201fa6 100644
--- a/lib/c/Makefile
+++ b/lib/c/Makefile
@@ -2,15 +2,15 @@
 
 # Use LLVM clang if it's found.
 CC = $(shell hash clang 2>/dev/null && echo clang || echo gcc)
-CFLAGS = -g -Wall -Werror -O3  -I. -Itest
+CFLAGS = -g -Wall -Werror -O3  -I. -Itest -DLABCOMM_ENCODER_LINEAR_SEARCH
 LDFLAGS = -L.
-LDLIBS_TEST = -lcunit -llabcomm
+LDLIBS_TEST = -Tlabcomm.linkscript  -lcunit -llabcomm
 
-OBJS= labcomm.o labcomm_dynamic_buffer_writer.o labcomm_fd_reader_writer.o labcomm_mem_reader.o labcomm_mem_writer.o
+OBJS= labcomm.o labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o labcomm_mem_reader.o labcomm_mem_writer.o
 LABCOMMC_PATH=../../compiler
 LABCOMMC_JAR=$(LABCOMMC_PATH)/labComm.jar
 
-TESTS=test_labcomm_private test_labcomm test_labcomm_errors
+TESTS=test_labcomm_basic_type_encoding test_labcomm test_labcomm_errors
 TEST_DIR=test
 TESTDATA_DIR=$(TEST_DIR)/testdata
 TEST_GEN_DIR=$(TESTDATA_DIR)/gen
@@ -42,9 +42,9 @@ labcomm.o : labcomm.c labcomm.h  labcomm_private.h
 
 labcomm_fd_reader_writer.o : labcomm_fd_reader_writer.c  labcomm_fd_reader_writer.h  labcomm.h  labcomm_private.h
 
-$(TEST_DIR)/labcomm_mem_reader.o: labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h
+#$(TEST_DIR)/labcomm_mem_reader.o: labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h
 
-$(TEST_DIR)/labcomm_mem_writer.o: labcomm_mem_writer.c labcomm_mem_writer.h cppmacros.h
+#$(TEST_DIR)/labcomm_mem_writer.o: labcomm_mem_writer.c labcomm_mem_writer.h cppmacros.h
 
 ethaddr.o: ethaddr.c
 
diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c
index 5256de8..bdcd204 100644
--- a/lib/c/labcomm.c
+++ b/lib/c/labcomm.c
@@ -7,11 +7,15 @@
 
 #include <errno.h>
 #include <string.h>
+#include <stdarg.h>
+
 #include "labcomm.h"
 #include "labcomm_private.h"
 #include "labcomm_ioctl.h"
 #include "labcomm_dynamic_buffer_writer.h"
 
+#define LABCOMM_VERSION "LabComm2013"
+
 typedef struct labcomm_sample_entry {
   struct labcomm_sample_entry *next;
   int index;
@@ -146,6 +150,8 @@ static labcomm_sample_entry_t *get_sample_by_index(
   return p;
 }
 
+#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
+
 static int get_encoder_index(
   labcomm_encoder_t *e,
   labcomm_signature_t *s)
@@ -163,6 +169,25 @@ static int get_encoder_index(
   return result;
 }
 
+#else
+
+static int get_encoder_index(
+  labcomm_encoder_t *e,
+  labcomm_signature_t *s)
+{
+  int result = 0;
+  extern  labcomm_signature_t labcomm_first_signature;
+  extern  labcomm_signature_t labcomm_last_signature;
+
+  if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
+    //fprintf(stderr, "%d\n", (int)(s - &labcomm_start));
+    result = s - &labcomm_first_signature + LABCOMM_USER;
+  }
+  return result;
+}
+
+#endif
+
 void labcomm_encoder_start(struct labcomm_encoder *e,
                            labcomm_signature_t *s) 
 {
@@ -301,12 +326,6 @@ void labcomm_internal_encode(
   }
 }
 
-void labcomm_internal_encoder_user_action(labcomm_encoder_t *e,
-					  int action)
-{
-  e->writer.write(&e->writer, action);
-}
-
 void labcomm_encoder_free(labcomm_encoder_t* e)
 {
   e->writer.write(&e->writer, labcomm_writer_free);
@@ -501,7 +520,7 @@ static int do_decode_one(labcomm_decoder_t *d)
 }
 
 labcomm_decoder_t *labcomm_decoder_new(
-  int (*reader)(labcomm_reader_t *, labcomm_reader_action_t),
+  int (*reader)(labcomm_reader_t *, labcomm_reader_action_t, ...),
   void *reader_context)
 {
   labcomm_decoder_t *result = malloc(sizeof(labcomm_decoder_t));
@@ -522,7 +541,7 @@ labcomm_decoder_t *labcomm_decoder_new(
     result->do_decode_one = do_decode_one;
     result->on_error = on_error_fprintf;
     result->on_new_datatype = on_new_datatype;
-    result->reader.read(&result->reader, labcomm_reader_alloc);
+    result->reader.read(&result->reader, labcomm_reader_alloc, LABCOMM_VERSION);
   }
   return result;
 }
diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h
index baedb8d..48d4cbe 100644
--- a/lib/c/labcomm.h
+++ b/lib/c/labcomm.h
@@ -1,20 +1,8 @@
 #ifndef _LABCOMM_H_
 #define _LABCOMM_H_
 
-#ifdef ARM_CORTEXM3_CODESOURCERY
-  #include <machine/endian.h>
-#else
-  #include <endian.h>
-#endif
-
-// Some projects can not use stdio.h.
-#ifndef LABCOMM_NO_STDIO
-  #include <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
 #include <stdarg.h>
+#include <unistd.h>
 
 /* Forward declaration */
 struct labcomm_encoder;
@@ -94,7 +82,8 @@ void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
  */
 
 typedef enum { 
-  labcomm_reader_alloc, 
+  labcomm_reader_alloc,     /* (..., char *labcomm_version)
+			       Allocate all neccessary data */
   labcomm_reader_free,
   labcomm_reader_start, 
   labcomm_reader_continue, 
@@ -108,13 +97,13 @@ typedef struct labcomm_reader {
   int data_size;
   int count;
   int pos;
-  int (*read)(struct labcomm_reader *, labcomm_reader_action_t);
+  int (*read)(struct labcomm_reader *, labcomm_reader_action_t, ...);
   int (*ioctl)(struct labcomm_reader *, int, va_list);
   labcomm_error_handler_callback on_error;
 }  labcomm_reader_t;
 
 struct labcomm_decoder *labcomm_decoder_new(
-  int (*reader)(labcomm_reader_t *, labcomm_reader_action_t),
+  int (*reader)(labcomm_reader_t *, labcomm_reader_action_t, ...),
   void *reader_context);
 int labcomm_decoder_decode_one(
   struct labcomm_decoder *decoder);
@@ -128,7 +117,8 @@ void labcomm_decoder_free(
  */
 
 typedef enum { 
-  labcomm_writer_alloc,              /* Allocate all neccessary data */
+  labcomm_writer_alloc,              /* (..., char *labcomm_version)
+					Allocate all neccessary data */
   labcomm_writer_free,               /* Free all allocated data */
   labcomm_writer_start,              /* Start writing an ordinary sample */
   labcomm_writer_continue,           /* Buffer full during ordinary sample */
diff --git a/lib/c/labcomm.linkscript b/lib/c/labcomm.linkscript
new file mode 100644
index 0000000..27cf28f
--- /dev/null
+++ b/lib/c/labcomm.linkscript
@@ -0,0 +1,8 @@
+SECTIONS { 
+  labcomm : {
+    labcomm_first_signature = ABSOLUTE(.) ;
+    *(labcomm)
+    labcomm_last_signature = ABSOLUTE(.) ;
+  }
+}
+INSERT AFTER .data;
diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c
index 5e180ec..4c20171 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.c
+++ b/lib/c/labcomm_dynamic_buffer_writer.c
@@ -1,4 +1,6 @@
 #include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
 #include "labcomm_ioctl.h"
 #include "labcomm_dynamic_buffer_writer.h"
 
diff --git a/lib/c/labcomm_fd_reader_writer.c b/lib/c/labcomm_fd_reader.c
similarity index 52%
rename from lib/c/labcomm_fd_reader_writer.c
rename to lib/c/labcomm_fd_reader.c
index 3ddafc4..62cb6b4 100644
--- a/lib/c/labcomm_fd_reader_writer.c
+++ b/lib/c/labcomm_fd_reader.c
@@ -1,18 +1,29 @@
 #include <errno.h>
 #include <unistd.h>
-#include "labcomm_fd_reader_writer.h"
+#include <stdlib.h>
+#include <string.h>
+#include "labcomm_fd_reader.h"
 
 #define BUFFER_SIZE 2048
 
 int labcomm_fd_reader(
   labcomm_reader_t *r, 
-  labcomm_reader_action_t action)
+  labcomm_reader_action_t action,
+  ...)
 {
   int result = -EINVAL;
   int *fd = r->context;
   
   switch (action) {
     case labcomm_reader_alloc: {
+      va_list ap;
+      va_start(ap, action);
+      char *version = va_arg(ap, char *);
+      char *tmp = strdup(version);
+
+      read(*fd, tmp, strlen(version));
+      free(tmp);
+
       r->data = malloc(BUFFER_SIZE);
       if (r->data) {
         r->data_size = BUFFER_SIZE;
@@ -23,6 +34,7 @@ int labcomm_fd_reader(
       }
       r->count = 0;
       r->pos = 0;
+      va_end(ap);
     } break;
     case labcomm_reader_start: 
     case labcomm_reader_continue: {
@@ -60,48 +72,3 @@ int labcomm_fd_reader(
   return result;
 }
 
-int labcomm_fd_writer(
-  labcomm_writer_t *w, 
-  labcomm_writer_action_t action, ...)
-{
-  int result = 0;
-  int *fd = w->context;
-
-  switch (action) {
-    case labcomm_writer_alloc: {
-      w->data = malloc(BUFFER_SIZE);
-      if (! w->data) {
-        result = -ENOMEM;
-        w->data_size = 0;
-        w->count = 0;
-        w->pos = 0;
-      } else {
-        w->data_size = BUFFER_SIZE;
-        w->count = BUFFER_SIZE;
-        w->pos = 0;
-      }
-    } break;
-    case labcomm_writer_free: {
-      free(w->data);
-      w->data = 0;
-      w->data_size = 0;
-      w->count = 0;
-      w->pos = 0;
-    } break;
-    case labcomm_writer_start: 
-    case labcomm_writer_start_signature: {
-      w->pos = 0;
-    } break;
-    case labcomm_writer_continue: 
-    case labcomm_writer_continue_signature: {
-      result = write(*fd, w->data, w->pos);
-      w->pos = 0;
-    } break;
-    case labcomm_writer_end: 
-    case labcomm_writer_end_signature: {
-      result = write(*fd, w->data, w->pos);
-      w->pos = 0;
-    } break;
-  }
-  return result;
-}
diff --git a/lib/c/labcomm_fd_reader.h b/lib/c/labcomm_fd_reader.h
new file mode 100644
index 0000000..c06cb3a
--- /dev/null
+++ b/lib/c/labcomm_fd_reader.h
@@ -0,0 +1,12 @@
+#ifndef _LABCOMM_FD_READER_H_
+#define _LABCOMM_FD_READER_H_
+
+#include "labcomm.h"
+
+extern int labcomm_fd_reader(
+  labcomm_reader_t *reader, 
+  labcomm_reader_action_t action,
+  ...);
+
+#endif
+
diff --git a/lib/c/labcomm_fd_reader_writer.h b/lib/c/labcomm_fd_reader_writer.h
deleted file mode 100644
index e5125d5..0000000
--- a/lib/c/labcomm_fd_reader_writer.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _LABCOMM_FD_READER_WRITER_H_
-#define _LABCOMM_FD_READER_WRITER_H_
-
-#include "labcomm.h"
-
-extern int labcomm_fd_reader(
-  labcomm_reader_t *reader, 
-  labcomm_reader_action_t action);
-
-extern int labcomm_fd_writer(
-  labcomm_writer_t *writer, 
-  labcomm_writer_action_t action,
-  ...);
-
-#endif
-
diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c
new file mode 100644
index 0000000..196e18f
--- /dev/null
+++ b/lib/c/labcomm_fd_writer.c
@@ -0,0 +1,61 @@
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "labcomm_fd_writer.h"
+
+#define BUFFER_SIZE 2048
+
+int labcomm_fd_writer(
+  labcomm_writer_t *w, 
+  labcomm_writer_action_t action,
+  ...)
+{
+  int result = 0;
+  int *fd = w->context;
+
+  switch (action) {
+    case labcomm_writer_alloc: {
+      va_list ap;
+      va_start(ap, action);
+      char *version = va_arg(ap, char *);
+
+      write(*fd, version, strlen(version));
+      w->data = malloc(BUFFER_SIZE);
+      if (! w->data) {
+        result = -ENOMEM;
+        w->data_size = 0;
+        w->count = 0;
+        w->pos = 0;
+      } else {
+        w->data_size = BUFFER_SIZE;
+        w->count = BUFFER_SIZE;
+        w->pos = 0;
+      }
+      va_end(ap);
+    } break;
+    case labcomm_writer_free: {
+      free(w->data);
+      w->data = 0;
+      w->data_size = 0;
+      w->count = 0;
+      w->pos = 0;
+    } break;
+    case labcomm_writer_start: 
+    case labcomm_writer_start_signature: {
+      w->pos = 0;
+    } break;
+    case labcomm_writer_continue: 
+    case labcomm_writer_continue_signature: {
+      result = write(*fd, w->data, w->pos);
+      w->pos = 0;
+    } break;
+    case labcomm_writer_end: 
+    case labcomm_writer_end_signature: {
+      result = write(*fd, w->data, w->pos);
+      w->pos = 0;
+    } break;
+  }
+  return result;
+}
diff --git a/lib/c/labcomm_fd_writer.h b/lib/c/labcomm_fd_writer.h
new file mode 100644
index 0000000..ea89eb2
--- /dev/null
+++ b/lib/c/labcomm_fd_writer.h
@@ -0,0 +1,12 @@
+#ifndef _LABCOMM_FD_WRITER_H_
+#define _LABCOMM_FD_WRITER_H_
+
+#include "labcomm.h"
+
+extern int labcomm_fd_writer(
+  labcomm_writer_t *writer, 
+  labcomm_writer_action_t action,
+  ...);
+
+#endif
+
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 2d67778..4271200 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -38,6 +38,12 @@
  */
 #define LABCOMM_USER     0x40
 
+/*
+ *
+ */
+#define LABCOMM_DECLARE_SIGNATURE(name) \
+  labcomm_signature_t name __attribute__((section("labcomm")))
+
 /*
  * Semi private decoder declarations
  */
@@ -194,34 +200,6 @@ static inline char *labcomm_decode_string(labcomm_decoder_t *d)
   return labcomm_read_string(&d->reader);
 }
 
-static inline int labcomm_buffer_read(struct labcomm_reader *r, 
-				      labcomm_reader_action_t action)
-{
-  // If this gets called, it is an error, 
-  // so note error and let producer proceed
-  r->context = r;
-  r->pos = 0;
-  return 0;
-}
-
-static inline int labcomm_buffer_reader_error(struct labcomm_reader *r) 
-{
-  return r->context != NULL;
-} 
-
-static inline void labcomm_buffer_reader_setup(
-  labcomm_reader_t *r,
-  void *data,
-  int length)
-{
-  r->context = NULL; // Used as error flag
-  r->data = data;  
-  r->data_size = length;
-  r->count = length;
-  r->pos = 0;
-  r->read = labcomm_buffer_read;
-}
-
 /*
  * Semi private encoder declarations
  */
diff --git a/lib/c/test/labcomm_mem_reader.c b/lib/c/test/labcomm_mem_reader.c
index 0c4e3f1..e111433 100644
--- a/lib/c/test/labcomm_mem_reader.c
+++ b/lib/c/test/labcomm_mem_reader.c
@@ -1,6 +1,8 @@
 #include "labcomm_mem_reader.h"
 
 #include <errno.h>
+#include <stdlib.h>
+#include <string.h>
 
 /* This implementation assumes labcomm will call end exactly once after each start
  * It is not allowed to save data in mcontext->enc_data,
@@ -13,7 +15,9 @@
  */
 
 // TODO make labcomm use result!
-int labcomm_mem_reader(labcomm_reader_t *r, labcomm_reader_action_t action)
+int labcomm_mem_reader(labcomm_reader_t *r, 
+		       labcomm_reader_action_t action,
+		       ...)
 {
   int result = -EINVAL;
   labcomm_mem_reader_context_t *mcontext = (labcomm_mem_reader_context_t *) r->context;
diff --git a/lib/c/test/labcomm_mem_reader.h b/lib/c/test/labcomm_mem_reader.h
index 5cac018..55b8ea9 100644
--- a/lib/c/test/labcomm_mem_reader.h
+++ b/lib/c/test/labcomm_mem_reader.h
@@ -12,6 +12,8 @@ struct labcomm_mem_reader_context_t {
   unsigned char *enc_data;
 };
 
-int labcomm_mem_reader( labcomm_reader_t *r, labcomm_reader_action_t action);
+int labcomm_mem_reader(labcomm_reader_t *r, 
+		       labcomm_reader_action_t action,
+		       ...);
 
 #endif
diff --git a/lib/c/test/labcomm_mem_writer.c b/lib/c/test/labcomm_mem_writer.c
index 294a471..4370361 100644
--- a/lib/c/test/labcomm_mem_writer.c
+++ b/lib/c/test/labcomm_mem_writer.c
@@ -2,6 +2,7 @@
 
 #include <stddef.h>  // For size_t.
 #include <stdarg.h>
+#include <stdlib.h>
 #include <errno.h>
 
 #include "labcomm.h"
diff --git a/lib/c/test/test_labcomm.c b/lib/c/test/test_labcomm.c
index fc4004c..1c5020f 100644
--- a/lib/c/test/test_labcomm.c
+++ b/lib/c/test/test_labcomm.c
@@ -2,6 +2,7 @@
 #include "CUnit/Basic.h"
 #include "CUnit/Console.h"
 #include <stdbool.h>
+#include <stdlib.h>
 
 #include <labcomm.h>
 #include <labcomm_mem_writer.h>
diff --git a/lib/c/test/test_labcomm_private.c b/lib/c/test/test_labcomm_basic_type_encoding.c
similarity index 97%
rename from lib/c/test/test_labcomm_private.c
rename to lib/c/test/test_labcomm_basic_type_encoding.c
index 33e2a1a..c8dfff7 100644
--- a/lib/c/test/test_labcomm_private.c
+++ b/lib/c/test/test_labcomm_basic_type_encoding.c
@@ -9,7 +9,7 @@ int test_write(struct labcomm_writer *w, labcomm_writer_action_t a, ...)
   exit(1);
 }
 
-int test_read(struct labcomm_reader *r, labcomm_reader_action_t a)
+int test_read(struct labcomm_reader *r, labcomm_reader_action_t a, ...)
 {
   fprintf(stderr, "test_read should not be called\n");
   exit(1);
@@ -40,7 +40,7 @@ static labcomm_decoder_t decoder = {
     .context = NULL,
     .data = buffer,
     .data_size = sizeof(buffer),
-    .count = sizeof(buffer),
+    .count = 0,
     .pos = 0,
     .read = test_read,
     .ioctl = NULL,
@@ -60,7 +60,8 @@ typedef unsigned char byte;
     encoder.writer.pos = 0;						\
     labcomm_encode_##type(&encoder, value);				\
     writer_assert(#type, __LINE__, expect_count, (uint8_t*)expect_bytes); \
-    decoder.reader.pos = 0;					\
+    decoder.reader.count = encoder.writer.pos;				\
+    decoder.reader.pos = 0;						\
     decoded = labcomm_decode_##type(&decoder);				\
     if (decoded != value) {						\
       fprintf(stderr, "Decode error" format " != " format " @%s:%d \n", value, decoded, \
-- 
GitLab