Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Show changes
Showing
with 373 additions and 990 deletions
/*
labcomm_decoder.c -- runtime for handling decoding of labcomm samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define LABCOMM_VERSION "LabComm2013"
#include <errno.h>
#include "labcomm.h"
#include "labcomm_private.h"
#include "labcomm_signature.h"
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
struct sample_entry {
int remote_index;
struct labcomm_signature *signature;
labcomm_decoder_function decode;
labcomm_handler_function handler;
void *context;
};
struct labcomm_decoder {
struct labcomm_reader *reader;
int reader_allocated;
struct labcomm_error_handler *error;
struct labcomm_memory *memory;
struct labcomm_scheduler *scheduler;
labcomm_error_handler_callback on_error;
labcomm_handle_new_datatype_callback on_new_datatype;
LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
};
struct labcomm_decoder *labcomm_decoder_new(
struct labcomm_reader *reader,
struct labcomm_error_handler *error,
struct labcomm_memory *memory,
struct labcomm_scheduler *scheduler)
{
struct labcomm_decoder *result;
result = labcomm_memory_alloc(memory, 0, sizeof(*result));
if (result) {
result->reader = reader;
result->reader->decoder = result;
result->reader->data = 0;
result->reader->data_size = 0;
result->reader->count = 0;
result->reader->pos = 0;
result->reader->error = 0;
result->reader_allocated = 0;
result->error = error;
result->memory = memory;
result->scheduler = scheduler;
LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
}
return result;
}
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
labcomm_reader_free(d->reader, d->reader->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
labcomm_memory_free(memory, 0, d);
}
static void collect_flat_signature(
struct labcomm_decoder *decoder,
struct labcomm_writer *writer)
{
int type = labcomm_read_packed32(decoder->reader);
if (type >= LABCOMM_USER) {
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
"Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type);
} else {
labcomm_write_packed32(writer, type);
switch (type) {
case LABCOMM_ARRAY: {
int dimensions, i;
dimensions = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, dimensions);
for (i = 0 ; i < dimensions ; i++) {
int n = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, n);
}
collect_flat_signature(decoder, writer);
} break;
case LABCOMM_STRUCT: {
int fields, i;
fields = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, fields);
for (i = 0 ; i < fields ; i++) {
char *name = labcomm_read_string(decoder->reader);
labcomm_write_string(writer, name);
labcomm_memory_free(decoder->memory, 1, name);
collect_flat_signature(decoder, writer);
}
} break;
case LABCOMM_BOOLEAN:
case LABCOMM_BYTE:
case LABCOMM_SHORT:
case LABCOMM_INT:
case LABCOMM_LONG:
case LABCOMM_FLOAT:
case LABCOMM_DOUBLE:
case LABCOMM_STRING: {
} break;
default: {
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
"Implement %s (2) for type 0x%x...\n", __FUNCTION__, type);
} break;
}
}
}
static int writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
{
int result;
va_list va;
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = labcomm_writer_ioctl(writer, writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind)
{
int result;
/* TODO: should the labcomm_dynamic_buffer_writer be
a permanent part of labcomm_decoder? */
struct labcomm_writer_action_context action_context = {
.next = NULL,
.action = labcomm_dynamic_buffer_writer_action,
.context = NULL
};
struct labcomm_writer writer = {
.action_context = &action_context,
.memory = d->memory,
.data = NULL,
.data_size = 0,
.count = 0,
.pos = 0,
.error = 0,
};
struct labcomm_signature signature, *local_signature;
int remote_index, local_index, err;
local_signature = NULL;
local_index = 0;
labcomm_writer_alloc(&writer, writer.action_context, "");
labcomm_writer_start(&writer, writer.action_context, 0, NULL, NULL);
remote_index = labcomm_read_packed32(d->reader); //int
signature.name = labcomm_read_string(d->reader);
signature.type = kind;
collect_flat_signature(d, &writer);
labcomm_writer_end(&writer, writer.action_context);
err = writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&signature.size);
if (err < 0) {
fprintf(stderr, "Failed to get size: %s\n", strerror(-err));
result = -ENOENT;
goto free_signature_name;
}
err = writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
&signature.signature);
if (err < 0) {
fprintf(stderr, "Failed to get pointer: %s\n", strerror(-err));
result = -ENOENT;
goto free_signature_name;
}
{
int i;
labcomm_scheduler_data_lock(d->scheduler);
LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) {
struct sample_entry *s;
int *remote_to_local;
result = -ENOENT;
s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->local, struct sample_entry, i);
if (s->signature &&
s->signature->type == signature.type &&
s->signature->size == signature.size &&
strcmp(s->signature->name, signature.name) == 0 &&
bcmp((void*)s->signature->signature, (void*)signature.signature,
signature.size) == 0) {
s->remote_index = remote_index;
local_signature = s->signature;
local_index = i;
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->remote_to_local, int,
remote_index);
*remote_to_local = i;
result = remote_index;
break;
}
}
labcomm_scheduler_data_unlock(d->scheduler);
if (local_signature) {
labcomm_reader_start(d->reader, d->reader->action_context,
local_index, remote_index, local_signature,
NULL);
labcomm_reader_end(d->reader, d->reader->action_context);
}
}
#if 0
if (! entry) {
/* Unknown datatype, bail out */
d->on_new_datatype(d, &signature);
result = -ENOENT;
} else if (entry->index && entry->index != remote_index) {
d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5,
"%s(): index mismatch '%s' (id=0x%x != 0x%x)\n",
__FUNCTION__, signature.name, entry->index, remote_index);
result = -ENOENT;
#endif
free_signature_name:
labcomm_memory_free(d->memory, 0, signature.name);
labcomm_writer_free(&writer, writer.action_context);
return result;
}
struct call_handler_context {
struct labcomm_reader *reader;
int local_index;
int remote_index;
struct labcomm_signature *signature;
labcomm_handler_function handler;
void *context;
};
static void call_handler(void *value, void *context)
{
struct call_handler_context *wrap = context;
if (wrap->reader->error >= 0) {
labcomm_reader_start(wrap->reader, wrap->reader->action_context,
wrap->local_index, wrap->remote_index, wrap->signature,
value);
wrap->handler(value, wrap->context);
labcomm_reader_end(wrap->reader, wrap->reader->action_context);
}
}
static void reader_alloc(struct labcomm_decoder *d)
{
if (!d->reader_allocated) {
d->reader_allocated = 1;
labcomm_reader_alloc(d->reader, d->reader->action_context,
LABCOMM_VERSION);
}
}
int labcomm_decoder_decode_one(struct labcomm_decoder *d)
{
int result, remote_index;
reader_alloc(d);
remote_index = labcomm_read_packed32(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (remote_index == LABCOMM_TYPEDEF || remote_index == LABCOMM_SAMPLE) {
result = decode_typedef_or_sample(d, 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);
} else {
result = -ENOENT;
}
}
out:
return result;
}
void labcomm_decoder_run(struct labcomm_decoder *d)
{
while (labcomm_decoder_decode_one(d) > 0) {
}
}
int labcomm_decoder_ioctl(struct labcomm_decoder *d,
uint32_t action,
...)
{
int result;
va_list va;
va_start(va, action);
result = labcomm_reader_ioctl(d->reader,
d->reader->action_context,
0, 0, NULL, action, va);
va_end(va);
return result;
}
int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d,
struct labcomm_signature *signature,
uint32_t action, va_list va)
{
int result;
int local_index, remote_index;
local_index = labcomm_signature_local_index(signature);
labcomm_scheduler_data_lock(d->scheduler);
remote_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->local,
struct sample_entry,
local_index)->remote_index;
labcomm_scheduler_data_unlock(d->scheduler);
result = labcomm_reader_ioctl(d->reader, d->reader->action_context,
local_index, remote_index,
signature, action, va);
return result;
}
int labcomm_internal_decoder_register(
struct labcomm_decoder *d,
struct labcomm_signature *signature,
labcomm_decoder_function decode,
labcomm_handler_function handler,
void *context)
{
int local_index;
struct sample_entry *entry;
reader_alloc(d);
local_index = labcomm_signature_local_index(signature);
if (local_index <= 0) { goto out; }
labcomm_reader_start(d->reader, d->reader->action_context,
local_index, 0, signature,
NULL);
labcomm_reader_end(d->reader, d->reader->action_context);
labcomm_scheduler_data_lock(d->scheduler);
entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->local, struct sample_entry,
local_index);
if (entry == NULL) { local_index = -ENOMEM; goto unlock; }
entry->remote_index = 0;
entry->signature = signature;
entry->decode = decode;
entry->handler = handler;
entry->context = context;
unlock:
labcomm_scheduler_data_unlock(d->scheduler);
out:
return local_index;
}
/*
labcomm_encoder.c -- handling encoding of labcomm samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define LABCOMM_VERSION "LabComm2013"
#include <errno.h>
#include "labcomm.h"
#include "labcomm_signature.h"
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
struct labcomm_encoder {
struct labcomm_writer *writer;
struct labcomm_error_handler *error;
struct labcomm_memory *memory;
struct labcomm_scheduler *scheduler;
LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
};
struct labcomm_encoder *labcomm_encoder_new(
struct labcomm_writer *writer,
struct labcomm_error_handler *error,
struct labcomm_memory *memory,
struct labcomm_scheduler *scheduler)
{
struct labcomm_encoder *result;
result = labcomm_memory_alloc(memory, 0, sizeof(*result));
if (result) {
result->writer = writer;
result->writer->encoder = result;
result->writer->data = NULL;
result->writer->data_size = 0;
result->writer->count = 0;
result->writer->pos = 0;
result->writer->error = 0;
result->error = error;
result->memory = memory;
result->scheduler = scheduler;
LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
labcomm_writer_alloc(result->writer,
result->writer->action_context, LABCOMM_VERSION);
}
return result;
}
void labcomm_encoder_free(struct labcomm_encoder* e)
{
struct labcomm_memory *memory = e->memory;
labcomm_writer_free(e->writer, e->writer->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int);
labcomm_memory_free(memory, 0, e);
}
int labcomm_internal_encoder_register(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
int result = -EINVAL;
int index, *done, err, i;
index = labcomm_signature_local_index(signature);
labcomm_scheduler_writer_lock(e->scheduler);
if (signature->type != LABCOMM_SAMPLE) { goto out; }
if (index <= 0) { goto out; }
done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, int, index);
if (*done) { goto out; }
*done = 1;
err = labcomm_writer_start(e->writer, e->writer->action_context,
index, signature, NULL);
if (err == -EALREADY) { result = 0; goto out; }
if (err != 0) { result = err; goto out; }
labcomm_write_packed32(e->writer, signature->type);
labcomm_write_packed32(e->writer, index);
labcomm_write_string(e->writer, signature->name);
for (i = 0 ; i < signature->size ; i++) {
if (e->writer->pos >= e->writer->count) {
labcomm_writer_flush(e->writer, e->writer->action_context);
}
e->writer->data[e->writer->pos] = signature->signature[i];
e->writer->pos++;
}
labcomm_writer_end(e->writer, e->writer->action_context);
result = e->writer->error;
out:
labcomm_scheduler_writer_unlock(e->scheduler);
return result;
}
int labcomm_internal_encode(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode,
void *value)
{
int result;
int index;
index = labcomm_signature_local_index(signature);
labcomm_scheduler_writer_lock(e->scheduler);
result = labcomm_writer_start(e->writer, e->writer->action_context,
index, signature, value);
if (result == -EALREADY) { result = 0; goto no_end; }
if (result != 0) { goto out; }
result = labcomm_write_packed32(e->writer, index);
if (result != 0) { goto out; }
result = encode(e->writer, value);
out:
labcomm_writer_end(e->writer, e->writer->action_context);
no_end:
labcomm_scheduler_writer_unlock(e->scheduler);
return result;
}
int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
uint32_t action,
...)
{
int result;
va_list va;
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = labcomm_writer_ioctl(encoder->writer,
encoder->writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
uint32_t action, va_list va)
{
int result = -ENOTSUP;
int index;
index = labcomm_signature_local_index(signature);
result = labcomm_writer_ioctl(encoder->writer,
encoder->writer->action_context,
index, signature, action, va);
return result;
}
/*
labcomm_error.h -- labcomm error declarations
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LABCOMM_ERROR_H__
#define __LABCOMM_ERROR_H__
enum labcomm_error {
#define LABCOMM_ERROR(name, description) name ,
#include "labcomm_error.h"
#undef LABCOMM_ERROR
};
struct labcomm_error_handler;
#endif
#ifdef LABCOMM_ERROR
LABCOMM_ERROR(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE,
"Encoder has no registration for this signature")
LABCOMM_ERROR(LABCOMM_ERROR_ENC_BUF_FULL,
"The labcomm buffer is full")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE,
"Decoder: Unknown datatype")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_INDEX_MISMATCH,
"Decoder: index mismatch")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND,
"Decoder: type not found")
LABCOMM_ERROR(LABCOMM_ERROR_UNIMPLEMENTED_FUNC,
"This function is not yet implemented")
LABCOMM_ERROR(LABCOMM_ERROR_MEMORY,
"Could not allocate memory")
LABCOMM_ERROR(LABCOMM_ERROR_USER_DEF,
"User defined error")
#endif
/*
labcomm_signature.h -- signature handling.
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "labcomm.h"
int labcomm_signature_local_index(struct labcomm_signature *s);
INPUT(liblabcomm.so.1)
/* Hack to get a link error with (hopefully) useful information if not linked
with -Tlabcomm.linkscript */
"You need to link with '-Tlabcomm.linkscript'"+=1;
/*INPUT(liblabcomm.a)*/
## Macros
UNAME_S=$(shell uname -s)
VERSION=2014
LIBVERSION=2014
ifeq ($(UNAME_S),Linux)
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
CFLAGS=-std=c99 -g -Wall -Werror -O3 -I.
CFLAGS_TEST=$(CFLAGS) -Itest
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION) -lrt
LD_LIBRARY_PATH_NAME=LD_LIBRARY_PATH
MAKESHARED=gcc -o $1 -shared -Wl,-soname,$2 $3 -lc -lrt
else ifeq ($(UNAME_S),Darwin)
#CC=$(CROSS_COMPILE)clang
#LD=$(CROSS_COMPILE)ld
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
CFLAGS=-g -Wall -Werror -O3 -I. -Itest \
-DLABCOMM_COMPAT=\"labcomm$(VERSION)_compat_osx.h\" \
-DLABCOMM_OS_DARWIN=1 \
-Wno-unused-function
# -Wno-tautological-compare
CFLAGS+=-std=c99
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION)
LD_LIBRARY_PATH_NAME=DYLD_LIBRARY_PATH
MAKESHARED=clang -o $1 -shared -Wl,-install_name,$2 $3 -lc
else ifneq ($(findstring CYGWIN,$(UNAME_S)),)
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CFLAGS=-std=c99 -g -Wall -Werror -O3 -I.
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION) -lrt
ALL_DEPS:=$(filter-out %.so.1, $(ALL_DEPS)) # No -fPIC supported in windows?
else
$(error Unknown system $(UNAME_S))
endif
CFLAGS_TEST=$(CFLAGS) -Itest -DVERSION=$(VERSION)
ifeq ($(CROSS_COMPILE),i586-wrs-vxworks-)
ALL_DEPS:=$(filter-out %.so.1, $(ALL_DEPS)) # PIC is only supported for RTPs
CFLAGS:=$(CFLAGS) -DLABCOMM_COMPAT=\"labcomm_compat_vxworks.h\"
endif
#include "CUnit/Basic.h"
#include "CUnit/Console.h"
#include <stdbool.h>
#include <stdlib.h>
#include <labcomm.h>
#include <labcomm_mem_writer.h>
#include <labcomm_mem_reader.h>
#include "test/testdata/gen/test_sample.h"
#define TEST_BUFFER_SIZE (50)
void test_error_handler(enum labcomm_error error_id, size_t nbr_va_args, ...);
int init_suit_labcomm()
{
return 0;
}
int clean_suit_labcomm()
{
return 0;
}
void setup_connected_encoder_decoder(struct labcomm_encoder **enc,
labcomm_mem_writer_context_t *enc_ctx,
struct labcomm_decoder **dec,
labcomm_mem_reader_context_t *dec_ctx)
{
enc_ctx->write_pos = 0;
enc_ctx->buf = malloc(TEST_BUFFER_SIZE);
enc_ctx->length = TEST_BUFFER_SIZE;
*enc = labcomm_encoder_new(labcomm_mem_writer, enc_ctx);
dec_ctx->size = 0;
dec_ctx->enc_data = enc_ctx->buf;
*dec = labcomm_decoder_new(labcomm_mem_reader, dec_ctx);
labcomm_register_error_handler_decoder(*dec, test_error_handler);
labcomm_register_error_handler_encoder(*enc, test_error_handler);
}
static bool in_error = false;
static enum labcomm_error in_error_id = LABCOMM_ERROR_ENUM_BEGIN_GUARD;
void test_error_handler(enum labcomm_error error_id, size_t nbr_va_args, ...)
{
in_error = true;
in_error_id = error_id;
}
static bool got_sample = false;
void test_decoder_handle_test_sample_test_var(test_sample_test_var *v, void *ctx)
{
got_sample = true;
}
void test_decoder_decode_sig()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_register_test_sample_test_var(decoder,
test_decoder_handle_test_sample_test_var, NULL);
labcomm_decoder_decode_one(decoder);
CU_ASSERT_FALSE(in_error);
enc_ctx.write_pos = 0;
test_sample_test_var var = 1;
labcomm_encode_test_sample_test_var(encoder, &var);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_decode_one(decoder);
CU_ASSERT_FALSE(in_error);
CU_ASSERT_FALSE(got_sample);
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
in_error = false;
in_error_id = LABCOMM_ERROR_ENUM_BEGIN_GUARD;
got_sample = false;
}
static bool got_new_datatype = false;
static labcomm_signature_t new_sig;
int test_new_datatype(struct labcomm_decoder *decoder,
labcomm_signature_t *sig)
{
got_new_datatype = true;
memcpy(&new_sig, sig, sizeof(labcomm_signature_t));
return 0;
}
void test_decode_unreg_signature_handle()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_register_new_datatype_handler(decoder, test_new_datatype);
labcomm_decoder_decode_one(decoder);
CU_ASSERT_TRUE(got_new_datatype);
CU_ASSERT_EQUAL(
memcmp(new_sig.signature, dec_ctx.enc_data, dec_ctx.size), 0);
got_new_datatype = false;
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
}
void test_decode_unreg_signature_error()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_decode_one(decoder);
CU_ASSERT_TRUE(in_error);
CU_ASSERT_EQUAL(in_error_id, LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE);
got_new_datatype = false;
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
}
int main()
{
CU_pSuite suite_decoder = NULL;
// Initialize CUnit test registry.
if (CUE_SUCCESS != CU_initialize_registry()) {
return CU_get_error();
}
// Add our test suites.
suite_decoder = CU_add_suite("transport_enc_dec",
init_suit_labcomm, clean_suit_labcomm);
if (suite_decoder == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (
(CU_add_test(suite_decoder, "test_decoder_decode_sig",
test_decoder_decode_sig) == NULL)
||
(CU_add_test(suite_decoder, "test_decode_unreg_signature_handle",
test_decode_unreg_signature_handle) == NULL)
||
(CU_add_test(suite_decoder, "test_decode_unreg_signature_error",
test_decode_unreg_signature_error) == NULL)
) {
CU_cleanup_registry();
return CU_get_error();
}
// Set verbosity.
CU_basic_set_mode(CU_BRM_VERBOSE);
/*CU_console_run_tests();*/
// Run all test suites.
CU_basic_run_tests();
// Clean up.
CU_cleanup_registry();
return CU_get_error();
}
sample int test_var;
#!/usr/bin/python
import os
import sys
import difflib
import re
class File:
def __init__(self, path, match, replacement):
def replace(s):
r = re.sub('[ \t]+', ' ', s).replace(match, replacement)
r = r.strip() + '\n'
return r
self.name = path.replace(match, replacement)
self.path = path
with open(path) as f:
self.lines = map(replace, f.readlines())
def __cmp__(self, other):
if other == None:
return cmp(self.name, other)
return cmp(self.name, other.name)
def readfiles(root, match, replacement):
result = []
for n in os.listdir(root):
path = os.path.join(root, n)
if os.path.islink(path):
pass
elif os.path.isdir(path):
for f in filter(None, readfiles(path, match, replacement)):
result.append(f)
else:
result.append(File(path, match, replacement))
for f in sorted(result):
yield f
yield None
if __name__ == '__main__':
A = readfiles(*sys.argv[1:4])
B = readfiles(*sys.argv[4:7])
a = A.next()
b = B.next()
while a != None or b != None:
if b == None or a.name < b.name:
print "Only in %s:" %sys.argv[1], a.path
a = A.next()
elif a == None or a.name > b.name:
print "Only in %s:" %sys.argv[4], b.path
b = B.next()
else:
equal = True
for l in difflib.unified_diff(a.lines, b.lines, a.path, b.path):
print l,
equal = False
if equal:
print "Identical", a.path, b.path
a = A.next()
b = B.next()
labcomm2014.dll
MODULES=LabCommDispatcher \
LabCommDecoderRegistry \
LabComm \
LabCommSample \
LabCommHandler \
LabCommEncoderRegistry \
LabCommDecoder \
LabCommType \
LabCommEncoderChannel \
LabCommEncoder \
LabCommDecoderChannel \
MODULES=Constant\
Decoder \
DecoderChannel \
DecoderRegistry \
Encoder \
EncoderChannel \
EncoderRegistry \
RenamingDecoder \
RenamingEncoder \
RenamingRegistry \
Sample \
SampleDispatcher \
SampleHandler \
SampleType \
WrappingDecoder \
WrappingEncoder
all: labcomm.dll
.PHONY: all
all: labcomm2014.dll
labcomm.dll: $(MODULES:%=se/lth/control/labcomm/%.cs) Makefile
labcomm2014.dll: $(MODULES:%=se/lth/control/labcomm2014/%.cs) Makefile
mcs -out:$@ -target:library $(filter %.cs, $^)
.PHONY: test
test:
.PHONY: clean
clean:
rm -f labcomm.dll
.PHONY: distclean
distclean:
rm -f labcomm2014.dll
namespace se.lth.control.labcomm {
public interface LabCommHandler {
}
}
\ No newline at end of file
public interface LabCommSample {
}
public interface LabCommType {
}
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
public class LabComm {
public class Constant {
public const string VERSION = "LabComm2013";
public const string CURRENT_VERSION = "LabComm2014";
/*
* Predeclared aggregate type indices
/*
* Allowed packet tags
*/
public const int VERSION = 0x01;
public const int SAMPLE_DEF = 0x02;
public const int SAMPLE_REF = 0x03;
public const int TYPE_DEF = 0x04;
public const int TYPE_BINDING = 0x05;
public const int PRAGMA = 0x3f;
public const int FIRST_USER_INDEX = 0x40; /* ..0xffffffff */
/*
* Predefined aggregate type indices
*/
public const int TYPEDEF = 0x01;
public const int SAMPLE = 0x02;
public const int ARRAY = 0x10;
public const int STRUCT = 0x11;
......@@ -23,12 +32,8 @@ namespace se.lth.control.labcomm {
public const int FLOAT = 0x25;
public const int DOUBLE = 0x26;
public const int STRING = 0x27;
public const int SAMPLE = 0x28;
/*
* start of user defined types
*/
public const int FIRST_USER_INDEX = 0x40;
}
}
using System;
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
public interface LabCommDecoder {
public interface Decoder {
void register(LabCommDispatcher dispatcher,
LabCommHandler handler);
void runOne();
void run();
void register(SampleDispatcher dispatcher,
SampleHandler handler);
void registerSampleRef(SampleDispatcher dispatcher);
bool decodeBoolean();
byte decodeByte();
......@@ -16,6 +19,7 @@ namespace se.lth.control.labcomm {
double decodeDouble();
String decodeString();
int decodePacked32();
SampleDispatcher decodeSampleRef();
}
......
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
public class LabCommDecoderChannel : LabCommDecoder {
public class DecoderChannel : Decoder {
private Stream stream;
private LabCommDecoderRegistry registry = new LabCommDecoderRegistry();
private DecoderRegistry def_registry = new DecoderRegistry();
private DecoderRegistry ref_registry = new DecoderRegistry();
byte[] buf = new byte[8];
public LabCommDecoderChannel(Stream stream) {
public DecoderChannel(Stream stream) {
this.stream = stream;
String version = decodeString();
if (version != LabComm.VERSION) {
throw new IOException("LabComm version mismatch " +
version + " != " + LabComm.VERSION);
}
}
public void runOne() {
bool done = false;
while (!done) {
int tag = decodePacked32();
int length = decodePacked32();
switch (tag) {
case LabComm.TYPEDEF:
case LabComm.SAMPLE: {
case Constant.VERSION: {
String version = decodeString();
if (version != Constant.CURRENT_VERSION) {
throw new IOException("LabComm version mismatch " +
version + " != " + Constant.CURRENT_VERSION);
}
} break;
case Constant.SAMPLE_DEF: {
int index = decodePacked32();
String name = decodeString();
MemoryStream signature = new MemoryStream();
collectFlatSignature(new LabCommEncoderChannel(signature, false));
registry.add(index, name, signature.ToArray());
String name = decodeIntentions();
int signature_length = decodePacked32();
byte[] signature = new byte[signature_length];
ReadBytes(signature, signature_length);
def_registry.add(index, name, signature);
} break;
case Constant.SAMPLE_REF: {
int index = decodePacked32();
String name = decodeIntentions();
int signature_length = decodePacked32();
byte[] signature = new byte[signature_length];
ReadBytes(signature, signature_length);
ref_registry.add(index, name, signature);
} break;
case Constant.TYPE_DEF:
case Constant.TYPE_BINDING: {
for(int i=0; i<length;i++){
decodeByte();
}
} break;
default: {
LabCommDecoderRegistry.Entry e = registry.get(tag);
DecoderRegistry.Entry e = def_registry.get(tag);
if (e == null) {
throw new IOException("Unhandled tag " + tag);
}
LabCommDispatcher d = e.getDispatcher();
SampleDispatcher d = e.getSampleDispatcher();
if (d == null) {
throw new IOException("No dispatcher for '" + e.getName() + "'" + e.getSignature());
}
LabCommHandler h = e.getHandler();
SampleHandler h = e.getHandler();
if (h == null) {
throw new IOException("No handler for '" + e.getName() +"'");
}
......@@ -59,45 +77,13 @@ namespace se.lth.control.labcomm {
}
}
private void collectFlatSignature(LabCommEncoder e) {
int type = decodePacked32();
e.encodePacked32(type);
switch (type) {
case LabComm.ARRAY: {
int dimensions = decodePacked32();
e.encodePacked32(dimensions);
for (int i = 0 ; i < dimensions ; i++) {
e.encodePacked32(decodePacked32());
}
collectFlatSignature(e);
} break;
case LabComm.STRUCT: {
int fields = decodePacked32();
e.encodePacked32(fields);
for (int i = 0 ; i < fields ; i++) {
e.encodeString(decodeString());
collectFlatSignature(e);
}
} break;
case LabComm.BOOLEAN:
case LabComm.BYTE:
case LabComm.SHORT:
case LabComm.INT:
case LabComm.LONG:
case LabComm.FLOAT:
case LabComm.DOUBLE:
case LabComm.STRING: {
} break;
default: {
throw new IOException("Unimplemented type=" + type);
}
}
e.end(null);
public void register(SampleDispatcher dispatcher,
SampleHandler handler) {
def_registry.add(dispatcher, handler);
}
public void register(LabCommDispatcher dispatcher,
LabCommHandler handler) {
registry.add(dispatcher, handler);
public void registerSampleRef(SampleDispatcher dispatcher) {
ref_registry.add(dispatcher, null);
}
private void ReadBytes(byte[] result, int length) {
......@@ -106,7 +92,7 @@ namespace se.lth.control.labcomm {
int count = stream.Read(result, offset, length - offset);
if (count <= 0)
throw new EndOfStreamException(
String.Format("End of stream reached with {0} bytes left to read",
String.Format("End of stream reached with {0} bytes left to read",
length - offset));
offset += count;
}
......@@ -129,7 +115,7 @@ namespace se.lth.control.labcomm {
public byte decodeByte() {
return (byte)ReadInt(1);
}
public short decodeShort() {
return (short)ReadInt(2);
}
......@@ -137,11 +123,11 @@ namespace se.lth.control.labcomm {
public int decodeInt() {
return (int)ReadInt(4);
}
public long decodeLong() {
return (long)ReadInt(8);
}
[StructLayout(LayoutKind.Explicit)]
private struct Int32SingleUnion {
......@@ -155,7 +141,7 @@ namespace se.lth.control.labcomm {
u.AsInt = (int)ReadInt(4);
return u.AsFloat;
}
public double decodeDouble() {
return BitConverter.Int64BitsToDouble(ReadInt(8));
}
......@@ -169,7 +155,7 @@ namespace se.lth.control.labcomm {
public int decodePacked32() {
Int64 res = 0;
bool cont = true;
bool cont = true;
do {
Int64 c = decodeByte();
......@@ -179,5 +165,41 @@ namespace se.lth.control.labcomm {
return (int) (res & 0xffffffff);
}
private byte[] decodeBytes() {
int len = decodePacked32();
byte[] result = new byte[len];
for(int i=0; i<len; i++) {
result[i] = decodeByte();
}
return result;
}
private String decodeIntentions() {
int numIntentions = decodePacked32();
string name = "";
for(int i = 0; i<numIntentions; i++) {
byte[] key = decodeBytes();
byte[] val = decodeBytes();
if(key.Length == 0) {
name = Encoding.UTF8.GetString(val, 0, val.Length);
}
}
return name;
}
}
public SampleDispatcher decodeSampleRef() {
int index = (int)ReadInt(4);
try {
DecoderRegistry.Entry e = ref_registry.get(index);
return e.getSampleDispatcher();
} catch (NullReferenceException) {
return null;
}
}
}
}
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
using System;
using System.Collections.Generic;
public class LabCommDecoderRegistry {
public class DecoderRegistry {
public class Entry {
private LabCommDispatcher dispatcher;
private LabCommHandler handler;
private SampleDispatcher dispatcher;
private SampleHandler handler;
private int index;
private String name;
private byte[] signature;
public Entry(LabCommDispatcher dispatcher,
LabCommHandler handler) {
public Entry(SampleDispatcher dispatcher,
SampleHandler handler) {
this.dispatcher = dispatcher;
this.name = dispatcher.getName();
this.signature = dispatcher.getSignature();
......@@ -27,19 +27,19 @@ namespace se.lth.control.labcomm {
this.signature = signature;
}
public LabCommDispatcher getDispatcher() {
public SampleDispatcher getSampleDispatcher() {
return dispatcher;
}
public void setDispatcher(LabCommDispatcher dispatcher) {
public void setSampleDispatcher(SampleDispatcher dispatcher) {
this.dispatcher = dispatcher;
}
public LabCommHandler getHandler() {
public SampleHandler getHandler() {
return handler;
}
public void setHandler(LabCommHandler handler) {
public void setHandler(SampleHandler handler) {
this.handler = handler;
}
......@@ -90,26 +90,26 @@ namespace se.lth.control.labcomm {
}
}
private Dictionary<Type, Entry> byClass;
private Dictionary<SampleDispatcher, Entry> byDispatcher;
private Dictionary<int, Entry> byIndex;
public LabCommDecoderRegistry() {
byClass = new Dictionary<Type, Entry>();
public DecoderRegistry() {
byDispatcher = new Dictionary<SampleDispatcher, Entry>();
byIndex = new Dictionary<int, Entry>();
}
public void add(LabCommDispatcher dispatcher,
LabCommHandler handler) {
public void add(SampleDispatcher dispatcher,
SampleHandler handler) {
lock(this) {
Entry e;
byClass.TryGetValue(dispatcher.getSampleClass(), out e);
byDispatcher.TryGetValue(dispatcher, out e);
if (e != null) {
e.check(dispatcher.getName(), dispatcher.getSignature());
e.setHandler(handler);
} else {
foreach (Entry e2 in byIndex.Values) {
if (e2.match(dispatcher.getName(), dispatcher.getSignature())) {
e2.setDispatcher(dispatcher);
e2.setSampleDispatcher(dispatcher);
e2.setHandler(handler);
e = e2;
break;
......@@ -117,7 +117,7 @@ namespace se.lth.control.labcomm {
}
if (e == null) {
e = new Entry(dispatcher, handler);
byClass.Add(dispatcher.getSampleClass(), e);
byDispatcher.Add(dispatcher, e);
}
}
}
......@@ -132,7 +132,7 @@ namespace se.lth.control.labcomm {
if (e != null) {
e.check(name, signature);
} else {
foreach (Entry e2 in byClass.Values) {
foreach (Entry e2 in byDispatcher.Values) {
if (e2.match(name, signature)) {
e2.setIndex(index);
e = e2;
......
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
using System;
public interface LabCommEncoder {
public interface Encoder {
void register(LabCommDispatcher dispatcher);
void begin(Type c);
void end(Type c);
void register(SampleDispatcher dispatcher);
void registerSampleRef(SampleDispatcher dispatcher);
void begin(SampleDispatcher dispatcher);
void end(SampleDispatcher dispatcher);
void encodeBoolean(bool value);
void encodeByte(byte value);
......@@ -17,6 +18,7 @@ namespace se.lth.control.labcomm {
void encodeDouble(double value);
void encodeString(String value);
void encodePacked32(Int64 value);
void encodeSampleRef(SampleDispatcher value);
}
......
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
public class LabCommEncoderChannel : LabCommEncoder {
public class EncoderChannel : Encoder {
private Stream writer;
private MemoryStream bytes = new MemoryStream();
private LabCommEncoderRegistry registry = new LabCommEncoderRegistry();
private EncoderRegistry def_registry = new EncoderRegistry();
private EncoderRegistry ref_registry = new EncoderRegistry();
byte[] buf = new byte[8];
private int current_tag;
public LabCommEncoderChannel(Stream writer, bool emitVersion) {
public EncoderChannel(Stream writer) {
this.writer = writer;
if (emitVersion) {
encodeString(LabComm.VERSION);
}
begin(Constant.VERSION);
encodeString(Constant.CURRENT_VERSION);
end(null);
}
public LabCommEncoderChannel(Stream writer) : this(writer, true) {
public void register(SampleDispatcher dispatcher) {
int index = def_registry.add(dispatcher);
begin(Constant.SAMPLE_DEF);
encodePacked32(index);
encodeIntentions(dispatcher.getName());
byte[] signature = dispatcher.getSignature();
encodePacked32(signature.Length);
for (int i = 0 ; i < signature.Length ; i++) {
encodeByte(signature[i]);
}
end(null);
}
public void register(LabCommDispatcher dispatcher) {
int index = registry.add(dispatcher);
encodePacked32(LabComm.SAMPLE);
public void registerSampleRef(SampleDispatcher dispatcher) {
int index = ref_registry.add(dispatcher);
begin(Constant.SAMPLE_REF);
encodePacked32(index);
encodeString(dispatcher.getName());
encodeIntentions(dispatcher.getName());
byte[] signature = dispatcher.getSignature();
encodePacked32(signature.Length);
for (int i = 0 ; i < signature.Length ; i++) {
encodeByte(signature[i]);
}
end(null);
}
public void begin(Type c) {
encodePacked32(registry.getTag(c));
private void begin(int tag) {
current_tag = tag;
bytes.SetLength(0);
}
public void begin(SampleDispatcher identity) {
begin(def_registry.getTag(identity));
}
public void end(Type c) {
public void end(SampleDispatcher identity) {
WritePacked32(writer, current_tag);
WritePacked32(writer, bytes.Length);
bytes.WriteTo(writer);
bytes.SetLength(0);
writer.Flush();
}
private void WritePacked32(Stream s, Int64 value) {
Int64 v = value & 0xffffffff;
int i;
for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) {
buf[i] = (byte)(v & 0x7f | (i!=0?0x80:0x00));
}
for (i = i - 1 ; i >= 0 ; i--) {
s.WriteByte(buf[i]);
}
}
private void WriteInt(Int64 value, int length) {
for (int i = length - 1 ; i >= 0 ; i--) {
buf[i] = (byte)(value & 0xff);
......@@ -96,16 +129,23 @@ namespace se.lth.control.labcomm {
}
public void encodePacked32(Int64 value) {
byte[] tmp = new byte[5];
Int64 v = value & 0xffffffff;
int i;
for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) {
tmp[i] = (byte)(v & 0x7f);
}
for (i = i - 1 ; i >= 0 ; i--) {
encodeByte((byte)(tmp[i] | (i!=0?0x80:0x00)));
WritePacked32(bytes, value);
}
private void encodeIntentions(String name) {
encodePacked32(1); // one intention field
encodePacked32(0); // empty key: name
encodeString(name);
}
public void encodeSampleRef(SampleDispatcher value) {
int index = 0;
try {
index = ref_registry.getTag(value);
} catch (NullReferenceException) {
}
WriteInt(index, 4);
}
}
}