diff --git a/lib/c/Makefile b/lib/c/Makefile
index a4868f184442aae0b395e5b08bd9185317eafb3b..dd08db025ec66e0511a55cdc55cd544cc846512f 100644
--- a/lib/c/Makefile
+++ b/lib/c/Makefile
@@ -2,7 +2,7 @@
 
 # Use LLVM clang if it's found.
 CC = $(shell hash clang 2>/dev/null && echo clang || echo gcc)
-CFLAGS = -g -Wall -Werror -I. -Itest
+CFLAGS = -g -Wall -Werror -O3  -I. -Itest
 LDFLAGS = -L.
 LDLIBS_TEST = -lcunit -llabcomm
 
@@ -10,6 +10,7 @@ OBJS= labcomm.o labcomm_dynamic_buffer_writer.o labcomm_fd_reader_writer.o labco
 LABCOMMC_PATH=../../compiler
 LABCOMMC_JAR=$(LABCOMMC_PATH)/labComm.jar
 
+TESTS=test_labcomm_private test_labcomm test_labcomm_errors
 TEST_DIR=test
 TESTDATA_DIR=$(TEST_DIR)/testdata
 TEST_GEN_DIR=$(TESTDATA_DIR)/gen
@@ -51,15 +52,15 @@ $(CREATED_DIRS):
 	mkdir -p $@
 
 ## NB! the tests need CUnit to be installed
-run-test: $(TEST_DIR)/test_labcomm $(TEST_DIR)/test_labcomm_errors \
-	  | $(TEST_DIR)
-	test/test_labcomm
-	test/test_labcomm_errors
+run-test: $(TESTS:%=run-test-%)
+
+run-test-%: $(TEST_DIR)/% | $(TEST_DIR)
+	$<
 
 $(TEST_DIR)/%.o: $(TEST_DIR)/%.c
 	$(CC) $(CFLAGS) -o $@ -c $<
 
-$(TEST_DIR)/%: $(TEST_DIR)/%.o | liblabcomm.a
+$(TEST_DIR)/%: $(TEST_DIR)/%.o liblabcomm.a
 	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(LDLIBS_TEST)
 
 $(TEST_GEN_DIR)/%.c $(TEST_GEN_DIR)/%.h: $(TESTDATA_DIR)/%.lc \
@@ -88,3 +89,4 @@ distclean: clean
 
 # Extra dependencies
 $(TEST_DIR)/test_labcomm:  $(TEST_GEN_DIR)/test_sample.o
+$(TEST_DIR)/test_labcomm_private.o: labcomm_private.h
diff --git a/lib/c/labcomm_dynamic_buffer_writer.h b/lib/c/labcomm_dynamic_buffer_writer.h
index 1591b11e905c5607ed7f54385089b8bd7615c984..c743c02662f2f19bbb52e09917f0f64379108d4a 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.h
+++ b/lib/c/labcomm_dynamic_buffer_writer.h
@@ -3,10 +3,6 @@
 
 #include "labcomm.h"
 
-extern int labcomm_dynamic_buffer_reader(
-  labcomm_reader_t *reader, 
-  labcomm_reader_action_t action);
-
 extern int labcomm_dynamic_buffer_writer(
   labcomm_writer_t *writer, 
   labcomm_writer_action_t action,
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 9d66f4433882660e72e052690b286823e48b0bce..00c9461468edb83465f886c9197680e1daf9725f 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -8,6 +8,7 @@
   #include <stdio.h>
 #endif
 
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include "labcomm.h"
@@ -117,31 +118,52 @@ LABCOMM_DECODE(long, long long)
 LABCOMM_DECODE(float, float)
 LABCOMM_DECODE(double, double)
 
+/* 
+ * Unpack a 32 bit unsigned number from a sequence bytes, where the 
+ * first byte is prefixed with a variable length bit pattern that
+ * indicates the number of bytes used for encoding. The encoding
+ * is inspired by the UTF-8 encoding.
+ *
+ * 0b0     - 1 byte  (0x00000000 - 0x0000007f)
+ * 0b10    - 2 bytes (0x00000080 - 0x00003fff)
+ * 0b110   - 3 bytes (0x00004000 - 0x001fffff)
+ * 0b1110  - 4 bytes (0x00200000 - 0x0fffffff)
+ * 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused]
+ */
 static inline unsigned int labcomm_unpack32(labcomm_reader_t *r)
 {
-  unsigned int res=0;
-  unsigned char i=0;
-  unsigned char cont=1;
-  do {
+  unsigned int result = 0;
+  int n, i;
+  unsigned char tag;
+
+  if (r->pos >= r->count) {	
+    r->read(r, labcomm_reader_continue);
+  }
+  tag = r->data[r->pos];
+  r->pos++;
+  if (tag < 0x80) {
+    n = 1;
+    result = tag;
+  } else if (tag < 0xc0) {
+    n = 2;
+    result = tag & 0x3f;
+  } else if (tag < 0xe0) {
+    n = 3;
+    result = tag & 0x1f;
+  } else if (tag < 0xf0) {
+    n = 4;
+    result = tag & 0x0f;
+  } else {
+    n = 5;
+  }
+  for (i = 1 ; i < n ; i++) {
     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++;
+    result = (result << 8) | r->data[r->pos];
     r->pos++;
-  } while(cont);
-  return res;
+  }
+  return result;
 }
 
 static inline unsigned int labcomm_decode_packed32(labcomm_decoder_t *d) 
@@ -229,13 +251,14 @@ void labcomm_internal_encode(
   labcomm_signature_t *signature, 
   void *value);
 
-/* Should these really be visible? */
-void labcomm_encoder_start(struct labcomm_encoder *e,
-                           labcomm_signature_t *s) ;
+void labcomm_encoder_start(
+  labcomm_encoder_t *encoder,
+  labcomm_signature_t *signature);
 
 //HERE BE DRAGONS: is the signature_t* needed here?
-void labcomm_encoder_end(struct labcomm_encoder *e,
-                           labcomm_signature_t *s) ;
+void labcomm_encoder_end(
+  labcomm_encoder_t *encoder,
+  labcomm_signature_t *signature);
 
 
 
@@ -284,28 +307,51 @@ LABCOMM_ENCODE(float, float)
 LABCOMM_ENCODE(double, double)
 
 /* 
- * Pack the 32 bit number data as a sequence of 7 bit chunks, represented in bytes 
- * with the high bit meaning that more data is to come.
+ * Pack the 32 bit unsigned number data as a sequence bytes, where the 
+ * first byte is prefixed with a variable length bit pattern that
+ * indicates the number of bytes used for encoding. The encoding
+ * is inspired by the UTF-8 encoding.
  *
- * The chunks are sent "little endian": each 7 bit chunk is more significant than
- * the previous.
- */ 
+ * 0b0     - 1 byte  (0x00000000 - 0x0000007f)
+ * 0b10    - 2 bytes (0x00000080 - 0x00003fff)
+ * 0b110   - 3 bytes (0x00004000 - 0x001fffff)
+ * 0b1110  - 4 bytes (0x00200000 - 0x0fffffff)
+ * 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused]
+ */
 static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data)
 {
-  unsigned int tmp; 
-
-  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++;
+  int n;
+  unsigned char tag;
+  unsigned char tmp[4] = { (data >> 24) & 0xff, 
+			   (data >> 16) & 0xff, 
+			   (data >>  8) & 0xff, 
+			   (data      ) & 0xff }; 
+  if (data < 0x80) {
+    n = 1;
+    tag = 0x00;
+  } else if (data < 0x4000) { 
+    n = 2;
+    tag = 0x80;
+  } else if (data < 0x200000) { 
+    n = 3;
+    tag = 0xc0;
+  } else if (data < 0x10000000) { 
+    n = 4;
+    tag = 0xe0;
+  } else  {
+    n = 5;
+    tag = 0xf0;
+  }
+  if (w->pos + n - 1 >= w->count) {	
+    w->write(w, labcomm_writer_continue, n);
+  }
+  switch (n) {
+    case 5: w->data[w->pos++] = tag; tag = 0;
+    case 4: w->data[w->pos++] = tmp[0] | tag; tag = 0;
+    case 3: w->data[w->pos++] = tmp[1] | tag; tag = 0;
+    case 2: w->data[w->pos++] = tmp[2] | tag; tag = 0;
+    case 1: w->data[w->pos++] = tmp[3] | tag;
+  }
 }
 
 static inline void labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int data) 
@@ -313,6 +359,7 @@ static inline void labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int da
     labcomm_pack32(&e->writer, data);				
 }
 
+
 static inline void labcomm_write_string(labcomm_writer_t *w, char *s)
 {
   int length, i; 
diff --git a/lib/c/test/test_labcomm_private.c b/lib/c/test/test_labcomm_private.c
new file mode 100644
index 0000000000000000000000000000000000000000..a529d4d6bbd190c6a92540cf7c4b5269aef4be69
--- /dev/null
+++ b/lib/c/test/test_labcomm_private.c
@@ -0,0 +1,142 @@
+#include <stdint.h>
+#include <string.h>
+#include "labcomm_private.h"
+
+
+int test_write(struct labcomm_writer *w, labcomm_writer_action_t a, ...)
+{
+  fprintf(stderr, "test_write should not be called\n");
+  exit(1);
+}
+
+int test_read(struct labcomm_reader *r, labcomm_reader_action_t a)
+{
+  fprintf(stderr, "test_read should not be called\n");
+  exit(1);
+}
+
+static unsigned char buffer[128];
+static labcomm_encoder_t encoder = {
+  .context = NULL,
+  .writer =  {
+    .context = NULL,
+    .data = buffer,
+    .data_size = sizeof(buffer),
+    .count = sizeof(buffer),
+    .pos = 0,
+    .error = 0,
+    .write = test_write,
+    .ioctl = NULL,
+    .on_error = NULL,
+  },
+  .do_register = NULL,
+  .do_encode = NULL,
+  .on_error = NULL,
+};
+
+static labcomm_decoder_t decoder = {
+  .context = NULL,
+  .reader =  {
+    .context = NULL,
+    .data = buffer,
+    .data_size = sizeof(buffer),
+    .count = sizeof(buffer),
+    .pos = 0,
+//    .error = 0,
+    .read = test_read,
+    .ioctl = NULL,
+    .on_error = NULL,
+  },
+  .do_register = NULL,
+//  .do_decode = NULL,
+  .on_error = NULL,
+};
+
+typedef unsigned int packed32;
+typedef unsigned char boolean;
+
+#define TEST_WRITE_READ(type, format, value, expect_count, expect_bytes) \
+  {									\
+    type decoded;							\
+    encoder.writer.pos = 0;						\
+    labcomm_encode_##type(&encoder, value);				\
+    writer_assert(#type, __LINE__, expect_count, (uint8_t*)expect_bytes); \
+    decoder.reader.pos = 0;					\
+    decoded = labcomm_decode_##type(&decoder);				\
+    if (decoded != value) {						\
+      fprintf(stderr, "Decode error" format " != " format " @%s:%d \n", value, decoded, \
+	      __FILE__, __LINE__);					\
+      exit(1);								\
+    }									\
+  }
+
+static void writer_assert(char *type,
+			  int line,
+			  int count,
+			  uint8_t *bytes)
+{
+  if (encoder.writer.pos != count) {
+    fprintf(stderr, 
+	    "Wrong number of bytes written for '%s' (%d != %d) @%s:%d\n",
+	   type, encoder.writer.pos, count, __FILE__, line);
+    exit(1);
+  }
+  if (memcmp(encoder.writer.data, bytes, count) != 0) {
+    int i;
+
+    fprintf(stderr, "Wrong bytes written for '%s' ( ", type);
+    for (i = 0 ; i < count ; i++) {
+      fprintf(stderr, "%2.2x ", encoder.writer.data[i]);
+    }
+    fprintf(stderr, "!= ");
+    for (i = 0 ; i < count ; i++) {
+      fprintf(stderr, "%2.2x ", bytes[i]);
+    }
+    fprintf(stderr, ") @%s:%d\n", __FILE__, line);
+    exit(1);
+  }
+}
+
+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(boolean, "%d", 0, 1, "\00");
+  TEST_WRITE_READ(short, "%d", 0, 2, "\x00\x00");
+  TEST_WRITE_READ(short, "%d", 0x7fff, 2, "\x7f\xff");
+  TEST_WRITE_READ(short, "%d", -1, 2, "\xff\xff");
+  TEST_WRITE_READ(int, "%d", 0, 4, "\x00\x00\x00\x00");
+  TEST_WRITE_READ(int, "%d", 0x7fffffff, 4, "\x7f\xff\xff\xff");
+  TEST_WRITE_READ(int, "%d", -1, 4, "\xff\xff\xff\xff");
+  TEST_WRITE_READ(float, "%f", 0.0, 4, "\x00\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", 1.0, 4, "\x3f\x80\x00\x00");
+  TEST_WRITE_READ(float, "%f", 2.0, 4, "\x40\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", 0.5, 4, "\x3f\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", 0.25, 4, "\x3e\x80\x00\x00");
+  TEST_WRITE_READ(float, "%f", -0.0, 4, "\x80\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", -1.0, 4, "\xbf\x80\x00\x00");
+  TEST_WRITE_READ(float, "%f", -2.0, 4, "\xc0\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", -0.5, 4, "\xbf\x00\x00\x00");
+  TEST_WRITE_READ(float, "%f", -0.25, 4, "\xbe\x80\x00\x00");
+  TEST_WRITE_READ(double, "%f", 0.0, 8, "\x00\x00\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", 1.0, 8, "\x3f\xf0\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", 2.0, 8, "\x40\x00\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", 0.5, 8, "\x3f\xe0\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", 0.25, 8, "\x3f\xd0\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", -0.0, 8, "\x80\x00\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", -1.0, 8, "\xbf\xf0\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", -2.0, 8, "\xc0\x00\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", -0.5, 8, "\xbf\xe0\x00\x00\x00\x00\x00\x00");
+  TEST_WRITE_READ(double, "%f", -0.25, 8, "\xbf\xd0\x00\x00\x00\x00\x00\x00");
+  fprintf(stderr, "%s succeded\n", __FILE__);
+  return 0;
+}
+