Commit 70b290de authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Changed writer interface from a funtion to a [const] vtable struct.

parent b5a801be
......@@ -6,13 +6,14 @@ CFLAGS = -g -Wall -Werror -O3 -I. -Itest -DLABCOMM_ENCODER_LINEAR_SEARCH
LDFLAGS = -L.
LDLIBS_TEST = -Tlabcomm.linkscript -lcunit -llabcomm
OBJS= labcomm.o labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_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
#FIXME: labcomm_mem_reader.o labcomm_mem_writer.o
LABCOMM_JAR=../../compiler/labComm.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding test_labcomm_generated_encoding
#test_labcomm
#FIXME: test_labcomm_errors
#
#FIXME: test_labcomm test_labcomm_errors
TEST_DIR=test
TESTDATA_DIR=$(TEST_DIR)/testdata
TEST_GEN_DIR=$(TESTDATA_DIR)/gen
......
......@@ -34,7 +34,7 @@
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
#define LABCOMM_VERSION "LabComm2013"
#define LABCOMM_VERSION "\x0bLabComm2013"
typedef struct labcomm_sample_entry {
struct labcomm_sample_entry *next;
......@@ -227,20 +227,22 @@ static int get_encoder_index(
void labcomm_encode_signature(struct labcomm_encoder *e,
labcomm_signature_t *signature)
{
int i;
e->writer.write(&e->writer, labcomm_writer_start_signature);
int i, index;
index = get_encoder_index(e, signature);
e->writer.action.start(&e->writer, e, index, signature, NULL);
labcomm_encode_packed32(e, signature->type);
labcomm_encode_packed32(e, get_encoder_index(e, signature));
labcomm_encode_packed32(e, index);
labcomm_encode_string(e, signature->name);
for (i = 0 ; i < signature->size ; i++) {
if (e->writer.pos >= e->writer.count) {
e->writer.write(&e->writer, labcomm_writer_continue);
e->writer.action.flush(&e->writer);
}
e->writer.data[e->writer.pos] = signature->signature[i];
e->writer.pos++;
}
e->writer.write(&e->writer, labcomm_writer_end_signature);
e->writer.action.end(&e->writer);
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
......@@ -363,25 +365,23 @@ static int do_encode(
void *value)
{
int result;
labcomm_writer_start_t lws;
lws.encoder = e;
lws.index = get_encoder_index(e, signature);
lws.signature = signature;
lws.value = value;
result = e->writer.write(&e->writer, labcomm_writer_start, &lws);
if (result == -EALREADY) { result = 0; goto out; }
int index;
index = get_encoder_index(e, signature);
result = e->writer.action.start(&e->writer, e, index, signature, value);
if (result == -EALREADY) { result = 0; goto no_end; }
if (result != 0) { goto out; }
result = labcomm_encode_packed32(e, lws.index);
result = labcomm_encode_packed32(e, index);
if (result != 0) { goto out; }
result = encode(e, value);
out:
e->writer.write(&e->writer, labcomm_writer_end, &lws);
e->writer.action.end(&e->writer);
no_end:
return result;
}
labcomm_encoder_t *labcomm_encoder_new(
int (*writer)(labcomm_writer_t *, labcomm_writer_action_t, ...),
const struct labcomm_writer_action action,
void *writer_context)
{
labcomm_encoder_t *result = malloc(sizeof(labcomm_encoder_t));
......@@ -402,13 +402,12 @@ labcomm_encoder_t *labcomm_encoder_new(
result->writer.count = 0;
result->writer.pos = 0;
result->writer.error = 0;
result->writer.write = writer;
result->writer.ioctl = NULL;
result->writer.action = action;
result->writer.on_error = on_error_fprintf;
result->do_register = do_encoder_register;
result->do_encode = do_encode;
result->on_error = on_error_fprintf;
result->writer.write(&result->writer, labcomm_writer_alloc);
result->writer.action.alloc(&result->writer, LABCOMM_VERSION);
}
return result;
}
......@@ -442,7 +441,7 @@ int labcomm_internal_encode(
void labcomm_encoder_free(labcomm_encoder_t* e)
{
e->writer.write(&e->writer, labcomm_writer_free);
e->writer.action.free(&e->writer);
labcomm_encoder_context_t *context = (labcomm_encoder_context_t *) e->context;
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
......@@ -466,11 +465,11 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
{
int result = -ENOTSUP;
if (encoder->writer.ioctl != NULL) {
if (encoder->writer.action.ioctl != NULL) {
va_list va;
va_start(va, action);
result = encoder->writer.ioctl(&encoder->writer, action, NULL, va);
result = encoder->writer.action.ioctl(&encoder->writer, action, NULL, va);
va_end(va);
}
return result;
......@@ -483,8 +482,9 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
{
int result = -ENOTSUP;
if (encoder->writer.ioctl != NULL) {
result = encoder->writer.ioctl(&encoder->writer, action, signature, va);
if (encoder->writer.action.ioctl != NULL) {
result = encoder->writer.action.ioctl(&encoder->writer, action,
signature, va);
}
return result;
}
......@@ -584,7 +584,7 @@ static int do_decode_one(labcomm_decoder_t *d)
/* TODO: should the labcomm_dynamic_buffer_writer be
a permanent part of labcomm_decoder? */
labcomm_encoder_t *e = labcomm_encoder_new(
labcomm_dynamic_buffer_writer, 0);
labcomm_dynamic_buffer_writer, NULL);
labcomm_signature_t signature;
labcomm_sample_entry_t *entry = NULL;
int index, err;
......@@ -592,11 +592,11 @@ static int do_decode_one(labcomm_decoder_t *d)
index = labcomm_decode_packed32(d); //int
signature.name = labcomm_decode_string(d);
signature.type = result;
e->writer.write(&e->writer, labcomm_writer_start);
e->writer.action.start(&e->writer, NULL, 0, NULL, NULL);
/* printf("do_decode_one: result = %x, index = %x, name=%s\n",
result, index, signature.name); */
collect_flat_signature(d, e);
e->writer.write(&e->writer, labcomm_writer_end);
e->writer.action.end(&e->writer);
err = labcomm_encoder_ioctl(e, LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&signature.size);
if (err < 0) {
......
......@@ -81,24 +81,14 @@ void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
* Decoder
*/
typedef enum {
labcomm_reader_alloc, /* (..., char *labcomm_version)
Allocate all neccessary data */
labcomm_reader_free,
labcomm_reader_start,
labcomm_reader_continue,
labcomm_reader_end,
labcomm_reader_ioctl
} labcomm_reader_action_t;
struct labcomm_reader;
struct labcomm_reader_action {
int (*alloc)(struct labcomm_reader *, char *labcomm_version);
int (*free)(struct labcomm_reader *);
int (*start)(struct labcomm_reader *);
int (*fill)(struct labcomm_reader *);
int (*end)(struct labcomm_reader *);
int (*fill)(struct labcomm_reader *);
int (*ioctl)(struct labcomm_reader *, int, labcomm_signature_t *, va_list);
};
......@@ -108,6 +98,7 @@ typedef struct labcomm_reader {
int data_size;
int count;
int pos;
int error;
struct labcomm_reader_action action;
labcomm_error_handler_callback on_error;
} labcomm_reader_t;
......@@ -130,26 +121,20 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
/*
* Encoder
*/
typedef struct {
struct labcomm_encoder *encoder;
int index;
labcomm_signature_t *signature;
void *value;
} labcomm_writer_start_t;
typedef enum {
labcomm_writer_alloc, /* (..., char *labcomm_version)
Allocate all neccessary data */
labcomm_writer_free, /* Free all allocated data */
labcomm_writer_start, /* (..., labcomm_writer_start_t *s)
-EALREADY skips further encoding
Start writing an ordinary sample */
labcomm_writer_continue, /* Buffer full during ordinary sample */
labcomm_writer_end, /* End writing ordinary sample */
labcomm_writer_start_signature, /* Start writing signature */
labcomm_writer_continue_signature, /* Buffer full during signature */
labcomm_writer_end_signature, /* End writing signature */
} labcomm_writer_action_t;
struct labcomm_writer;
struct labcomm_writer_action {
int (*alloc)(struct labcomm_writer *w, char *labcomm_version);
int (*free)(struct labcomm_writer *w);
int (*start)(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
labcomm_signature_t *signature,
void *value);
int (*end)(struct labcomm_writer *w);
int (*flush)(struct labcomm_writer *w);
int (*ioctl)(struct labcomm_writer *w, int, labcomm_signature_t *, va_list);
};
typedef struct labcomm_writer {
void *context;
......@@ -158,13 +143,12 @@ typedef struct labcomm_writer {
int count;
int pos;
int error;
int (*write)(struct labcomm_writer *, labcomm_writer_action_t, ...);
int (*ioctl)(struct labcomm_writer *, int, labcomm_signature_t *, va_list);
struct labcomm_writer_action action;
labcomm_error_handler_callback on_error;
} labcomm_writer_t;
struct labcomm_encoder *labcomm_encoder_new(
int (*writer)(labcomm_writer_t *, labcomm_writer_action_t, ...),
const struct labcomm_writer_action action,
void *writer_context);
void labcomm_encoder_free(
struct labcomm_encoder *encoder);
......
......@@ -4,11 +4,78 @@
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
static int labcomm_dynamic_buffer_writer_ioctl(
struct labcomm_writer *w,
int action,
labcomm_signature_t *signature,
va_list arg)
static int dyn_alloc(struct labcomm_writer *w, char *labcomm_version)
{
w->data_size = 1000;
w->count = w->data_size;
w->data = malloc(w->data_size);
if (w->data == NULL) {
w->error = -ENOMEM;
}
w->pos = 0;
return w->error;
}
static int dyn_free(struct labcomm_writer *w)
{
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
return 0;
}
static int dyn_start(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
labcomm_signature_t *signature,
void *value)
{
void *tmp;
w->data_size = 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
w->error = 0;
} else {
w->error = -ENOMEM;
}
w->pos = 0;
return w->error;
}
static int dyn_end(struct labcomm_writer *w)
{
return 0;
}
static int dyn_flush(struct labcomm_writer *w)
{
void *tmp;
w->data_size += 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
w->error = 0;
} else {
w->error = -ENOMEM;
}
return w->error;
}
static int dyn_ioctl(struct labcomm_writer *w,
int action,
labcomm_signature_t *signature,
va_list arg)
{
int result = -ENOTSUP;
switch (action) {
......@@ -26,59 +93,11 @@ static int labcomm_dynamic_buffer_writer_ioctl(
return result;
}
int labcomm_dynamic_buffer_writer(
labcomm_writer_t *w,
labcomm_writer_action_t action,
...)
{
switch (action) {
case labcomm_writer_alloc: {
w->data_size = 1000;
w->count = w->data_size;
w->data = malloc(w->data_size);
if (w->data == NULL) {
w->error = -ENOMEM;
}
w->pos = 0;
w->ioctl = labcomm_dynamic_buffer_writer_ioctl;
} break;
case labcomm_writer_start:
case labcomm_writer_start_signature: {
void *tmp;
w->data_size = 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
w->error = 0;
} else {
w->error = -ENOMEM;
}
w->pos = 0;
} break;
case labcomm_writer_continue:
case labcomm_writer_continue_signature: {
void *tmp;
w->data_size += 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
} else {
w->error = -ENOMEM;
}
} break;
case labcomm_writer_end:
case labcomm_writer_end_signature: {
} break;
case labcomm_writer_free: {
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} break;
}
return w->error;
}
const struct labcomm_writer_action labcomm_dynamic_buffer_writer = {
.alloc = dyn_alloc,
.free = dyn_free,
.start = dyn_start,
.end = dyn_end,
.flush = dyn_flush,
.ioctl = dyn_ioctl
};
......@@ -3,9 +3,6 @@
#include "labcomm.h"
extern int labcomm_dynamic_buffer_writer(
labcomm_writer_t *writer,
labcomm_writer_action_t action,
...);
extern const struct labcomm_writer_action labcomm_dynamic_buffer_writer;
#endif
......@@ -7,59 +7,70 @@
#define BUFFER_SIZE 2048
int labcomm_fd_writer(
labcomm_writer_t *w,
labcomm_writer_action_t action,
...)
static int fd_alloc(struct labcomm_writer *w, char *version)
{
int result = 0;
#ifndef LABCOMM_FD_OMIT_VERSION
int *fd = w->context;
write(*fd, version, strlen(version));
#endif
w->data = malloc(BUFFER_SIZE);
if (! w->data) {
w->error = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} else {
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
}
switch (action) {
case labcomm_writer_alloc: {
#ifndef LABCOMM_FD_OMIT_VERSION
va_list ap;
va_start(ap, action);
char *version = va_arg(ap, char *);
return w->error;
}
write(*fd, version, strlen(version));
#endif
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;
}
#ifndef LABCOMM_FD_OMIT_VERSION
va_end(ap);
#endif
} 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;
static int fd_free(struct labcomm_writer *w)
{
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
return 0;
}
static int fd_start(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
labcomm_signature_t *signature,
void *value)
{
w->pos = 0;
return w->error;
}
static int fd_flush(struct labcomm_writer *w)
{
int *fd = w->context;
int err;
err = write(*fd, w->data, w->pos);
if (err < 0) {
w->error = -errno;
} else if (err == 0) {
w->error = -EINVAL;
}
return result;
w->pos = 0;
return w->error;
}
const struct labcomm_writer_action labcomm_fd_writer = {
.alloc = fd_alloc,
.free = fd_free,
.start = fd_start,
.end = fd_flush,
.flush = fd_flush,
.ioctl = NULL
};
......@@ -3,10 +3,7 @@
#include "labcomm.h"
extern int labcomm_fd_writer(
labcomm_writer_t *writer,
labcomm_writer_action_t action,
...);
extern const struct labcomm_writer_action labcomm_fd_writer;
#endif
......@@ -221,7 +221,7 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (w->pos >= w->count) { /*buffer is full*/ \
int err; \
err = w->write(w, labcomm_writer_continue); \
err = w->action.flush(w); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
......@@ -241,7 +241,7 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
for (i = 0 ; i < sizeof(type) ; i++) { \
if (w->pos >= w->count) { \
int err; \
err = w->write(w, labcomm_writer_continue); \
err = w->action.flush(w); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
......@@ -263,95 +263,6 @@ 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
* 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 int labcomm_write_packed32(labcomm_writer_t *w,
unsigned int data)
{
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;
}
/* TODO: maybe?
if (w->pos + n - 1 >= w->count) {
w->write(w, labcomm_writer_continue, n);
}
*/
switch (n) {
case 5: {
if (w->pos >= w->count) {
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}