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
Select Git revision

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Select Git revision
Show changes
Showing
with 583 additions and 1401 deletions
/*
test_labcomm2014_renaming.c -- LabComm tests of renaming
Copyright 2015 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "labcomm2014_private.h"
#include "labcomm2014_default_error_handler.h"
#include "labcomm2014_default_memory.h"
#include "labcomm2014_default_scheduler.h"
#include "labcomm2014_renaming.h"
#include "labcomm2014_renaming_encoder.h"
#include "test/gen/generated_encoding.h"
#define IOCTL_WRITER_ASSERT_BYTES 4096
#define IOCTL_WRITER_RESET 4097
#define EXPECT(...) \
{ \
int expected[] = __VA_ARGS__; \
labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, \
__LINE__, \
sizeof(expected)/sizeof(expected[0]), \
expected); \
}
#define VARIABLE(i) -(i + 1)
#define IS_VARIABLE(i) (i < 0)
static unsigned char buffer[128];
struct labcomm2014_writer *writer;
static int seen_variable[1024];
static int buf_writer_alloc(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
writer = w; /* Hack */
w->data_size = sizeof(buffer);
w->count = w->data_size;
w->data = buffer;
w->pos = 0;
return 0;
}
static int buf_writer_free(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
return 0;
}
static int buf_writer_start(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context,
int index,
const struct labcomm2014_signature *signature,
void *value)
{
return 0;
}
static int buf_writer_end(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
return 0;
}
static int buf_writer_flush(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
fprintf(stderr, "Should not come here %s:%d\n", __FILE__, __LINE__);
exit(1);
return 0;
}
static int buf_writer_ioctl(
struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context,
int signature_index, const struct labcomm2014_signature *signature,
uint32_t action, va_list arg)
{
int result = -ENOTSUP;
switch (action) {
case IOCTL_WRITER_ASSERT_BYTES: {
int line = va_arg(arg, int);
int count = va_arg(arg, int);
int *expected = va_arg(arg, int *);
int i, mismatch;
mismatch = 0;
if (w->pos != count) {
fprintf(stderr, "Invalid length detected %d != %d (%s:%d)\n",
w->pos, count, __FILE__, line);
mismatch = 1;
}
for (i = 0 ; i < count ; i++) {
if (IS_VARIABLE(expected[i])) {
if (seen_variable[VARIABLE(expected[i])] == -1) {
seen_variable[VARIABLE(expected[i])] = buffer[i];
}
if (seen_variable[VARIABLE(expected[i])] != buffer[i]) {
fprintf(stderr, "Unexpected variable v%d (%02x: != %02x)\n",
VARIABLE(expected[i]),
seen_variable[VARIABLE(expected[i])], buffer[i]);
mismatch = 1;
}
} else if (expected[i] != buffer[i]) {
mismatch = 1;
}
}
if (mismatch) {
fprintf(stderr, "Encoder mismatch (%s:%d)\n",
__FILE__, line);
for (i = 0 ; i < w->pos ; i++) {
if (32 <= w->data[i] && w->data[i] < 127) {
printf("%2c ", w->data[i]);
} else {
printf("%2.2x ", w->data[i]);
}
}
printf("\n");
for (i = 0 ; i < w->pos ; i++) {
printf("%2.2x ", w->data[i]);
}
printf("\n");
for (i = 0 ; i < count ; i++) {
if (expected[i] < 0) {
printf("v%d ", VARIABLE(expected[i]));
} else {
printf("%2.2x ", expected[i] );
}
}
printf("\n");
if (mismatch) { exit(1); }
}
result = 0;
} break;
case IOCTL_WRITER_RESET: {
w->pos = 0;
result = 0;
}
}
return result;
}
const struct labcomm2014_writer_action writer_action = {
.alloc = buf_writer_alloc,
.free = buf_writer_free,
.start = buf_writer_start,
.end = buf_writer_end,
.flush = buf_writer_flush,
.ioctl = buf_writer_ioctl
};
static struct labcomm2014_writer_action_context action_context = {
.next = NULL,
.action = &writer_action,
.context = NULL
};
static struct labcomm2014_writer buffer_writer = {
.action_context = &action_context,
.data = buffer,
.data_size = sizeof(buffer),
.count = sizeof(buffer),
.pos = 0,
.error = 0,
};
void dump_encoder(struct labcomm2014_encoder *encoder)
{
int i;
for (i = 0 ; i < writer->pos ; i++) {
printf("%2.2x ", writer->data[i]);
}
printf("\n");
}
static int do_test(int argc, char *argv[])
{
struct labcomm2014_renaming_registry *registry;
struct labcomm2014_encoder *encoder, *prefix, *suffix;
int i;
for (i = 0 ; i < sizeof(seen_variable)/sizeof(seen_variable[0]) ; i++) {
seen_variable[i] = -1;
}
registry = labcomm2014_renaming_registry_new(
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
encoder = labcomm2014_encoder_new(
&buffer_writer,
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
prefix = labcomm2014_renaming_encoder_new(encoder,
registry,
labcomm2014_renaming_prefix,
"p.");
suffix = labcomm2014_renaming_encoder_new(prefix,
registry,
labcomm2014_renaming_suffix,
".s");
EXPECT({ 0x01, 0x0c, 0x0b,
'L', 'a', 'b', 'C', 'o', 'm', 'm', '2','0', '1', '4' });
labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
/* Register twice to make sure that only one registration gets encoded */
labcomm2014_encoder_register_generated_encoding_V(encoder);
labcomm2014_encoder_register_generated_encoding_V(encoder);
EXPECT({ 0x02, 0x08, VARIABLE(0), 0x01, 0x00, 0x01, 'V', 0x02, 0x11, 0x00,
0x04, 0x0a, VARIABLE(1), 0x01, 0x00, 0x03, 'v', '_', 't', 0x02, 0x11, 0x00,
0x04, 0x07, VARIABLE(2), 0x01, 0x00, 0x01, 'V', 0x01, VARIABLE(1),
0x05, 0x02, VARIABLE(0), VARIABLE(2) });
labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
labcomm2014_encoder_register_generated_encoding_V(prefix);
labcomm2014_encoder_register_generated_encoding_V(prefix);
EXPECT({ 0x02, 0x0a, VARIABLE(3), 0x01, 0x00, 0x03, 'p', '.', 'V', 0x02, 0x11, 0x00,
0x04, 0x09, VARIABLE(4), 0x01, 0x00, 0x03, 'p', '.', 'V', 0x01, VARIABLE(2),
0x05, 0x02, VARIABLE(3), VARIABLE(4) });
labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
labcomm2014_encoder_register_generated_encoding_V(suffix);
labcomm2014_encoder_register_generated_encoding_V(suffix);
// XXX HERE BE DRAGONS! What does "BOGUS" man in the below renaming test?
// previous version (from merge conflict): VARIABLE(6) vs VARIABLE(2)
// <<<<<<< ours
// EXPECT({ 0x02, 0x0c, VARIABLE(5), 0x01, 0x00, 0x05, 'p', '.', 'V', '.', 's', 0x02, 0x11, 0x00,
// 0x04, 0x09, VARIABLE(6), 0x01, 0x00, 0x03, 'V', '.', 's', 0x01, VARIABLE(2),
// 0x04, 0x0b, VARIABLE(7), 0x01, 0x00, 0x05, 'p', '.', 'V', '.', 's', 0x01, VARIABLE(6),
// =======
EXPECT({ 0x02, 0x0c, VARIABLE(5), 0x01, 0x00, 0x05, 'p', '.', 'V', '.', 's', 0x02, 0x11, 0x00,
0x04, 0x09, VARIABLE(6), 0x01, 0x00, 0x03, 'V', '.', 's', 0x01, VARIABLE(2), /* BOGUS */
0x04, 0x0b, VARIABLE(7), 0x01, 0x00, 0x05, 'p', '.', 'V', '.', 's', 0x01, VARIABLE(2),
0x05, 0x02, VARIABLE(5), VARIABLE(7) });
labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
/* Register twice to make sure that only one registration gets encoded */
labcomm2014_encoder_sample_ref_register(encoder,
labcomm2014_signature_generated_encoding_V);
labcomm2014_encoder_sample_ref_register(encoder,
labcomm2014_signature_generated_encoding_V);
EXPECT({0x03, 0x08, VARIABLE(8), 0x01, 0x00, 0x01, 'V', 0x02, 0x11, 0x00});
labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
/* Register twice to make sure that only one registration gets encoded */
labcomm2014_encoder_sample_ref_register(prefix,
labcomm2014_signature_generated_encoding_V);
labcomm2014_encoder_sample_ref_register(prefix,
labcomm2014_signature_generated_encoding_V);
EXPECT({0x03, 0x0a, VARIABLE(9), 0x01, 0x00, 0x03, 'p', '.', 'V', 0x02, 0x11, 0x00});
labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
/* Register twice to make sure that only one registration gets encoded */
labcomm2014_encoder_sample_ref_register(suffix,
labcomm2014_signature_generated_encoding_V);
labcomm2014_encoder_sample_ref_register(suffix,
labcomm2014_signature_generated_encoding_V);
EXPECT({0x03, 0x0c, VARIABLE(10), 0x01, 0x00, 0x05, 'p', '.', 'V', '.', 's', 0x02, 0x11, 0x00});
labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm2014_encode_generated_encoding_V(encoder);
EXPECT({VARIABLE(0), 0x00 });
labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
labcomm2014_encode_generated_encoding_V(prefix);
EXPECT({VARIABLE(3), 0x00 });
labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
labcomm2014_encode_generated_encoding_V(suffix);
EXPECT({VARIABLE(5), 0x00 });
labcomm2014_encoder_free(suffix);
labcomm2014_encoder_free(prefix);
labcomm2014_encoder_free(encoder);
labcomm2014_renaming_registry_free(registry);
return 0;
}
int main(int argc, char *argv[])
{
return do_test(argc, argv);
}
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <err.h>
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#include "labcomm2014_default_error_handler.h"
#include "labcomm2014_default_memory.h"
#include "labcomm2014_default_scheduler.h"
#include "labcomm2014_renaming.h"
#include "labcomm2014_renaming_private.h"
#include "test/gen/generated_encoding.h"
static int do_test(int argc, char **argv)
{
struct labcomm2014_renaming_registry *registry;
struct labcomm2014_renaming_rename *r1, *r2, *r3, *r4;
registry = labcomm2014_renaming_registry_new(
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
r1 = labcomm2014_renaming_rename_new(
registry,
labcomm2014_signature_generated_encoding_R,
labcomm2014_renaming_prefix, "p:");
r2 = labcomm2014_renaming_rename_new(
registry,
labcomm2014_renaming_rename_signature(r1),
labcomm2014_renaming_suffix, ":s");
r3 = labcomm2014_renaming_rename_new(
registry,
labcomm2014_signature_generated_encoding_R,
labcomm2014_renaming_suffix, ":s");
r4 = labcomm2014_renaming_rename_new(
registry,
labcomm2014_renaming_rename_signature(r3),
labcomm2014_renaming_prefix, "p:");
assert(r2 == r4);
labcomm2014_renaming_rename_free(registry, r1);
labcomm2014_renaming_rename_free(registry, r2);
labcomm2014_renaming_rename_free(registry, r3);
labcomm2014_renaming_rename_free(registry, r4);
labcomm2014_renaming_registry_free(registry);
return 0;
}
int main(int argc, char **argv)
{
return do_test(argc, argv);
}
sample int test_var[_,2,_];
#include <stdlib.h>
#include <stdio.h>
#include "labcomm2014_private.h"
#include "test/gen/another_encoding.h"
#include "test/gen/generated_encoding.h"
static void info(char *name, char *full_name,
const struct labcomm2014_signature *signature) {
printf("%s %s %p -> %d\n", name, full_name, signature,
labcomm2014_get_local_index(signature));
if (labcomm2014_get_local_index(signature) < 0x40) {
exit(1);
}
};
int main(int argc, char *argv[])
{
#define FUNC(name, full_name) \
info( #name, #full_name, labcomm2014_signature_##full_name)
LABCOMM_FORALL_SAMPLES_generated_encoding(FUNC, ;);
LABCOMM_FORALL_SAMPLES_another_encoding(FUNC, ;);
return 0;
}
## Macros
VERSIONS=2014
# Use LLVM clang if it's found.
CC = $(shell hash clang 2>/dev/null && echo clang || echo gcc)
CFLAGS = -g -Wall -I .
LDFLAGS = -L .
LDLIBS_TEST = -lcunit -llabcomm
all:
OBJS= labcomm.o labcomm_fd_reader_writer.o labcomm_mem_reader.o labcomm_mem_writer.o
LABCOMMC_PATH=../../compiler
LABCOMMC_JAR=$(LABCOMMC_PATH)/labComm.jar
%:
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
TEST_DIR=test
TESTDATA_DIR=$(TEST_DIR)/testdata
TEST_GEN_DIR=$(TESTDATA_DIR)/gen
CREATED_DIRS=$(TEST_DIR) $(TESTDATA_DIR) $(TEST_GEN_DIR)
# Disable experimental objects by invoking make like `make -e LABCOMM_NO_EXPERIMENTAL=true`
ifneq ($(LABCOMM_NO_EXPERIMENTAL),true)
OBJS += experimental/udp_hack.o experimental/ethaddr.o \
experimental/labcomm_thr_reader_writer.o \
experimental/ThrottleDrv/ethernet_drv.o \
experimental/ThrottleDrv/throttle_drv.o \
experimental/labcomm_udp_reader_writer.o
endif
## Targets
.PHONY: all run-test clean distclean
all: liblabcomm.a test/test_labcomm_errors
liblabcomm.a: $(OBJS)
ar -r liblabcomm.a $^
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
labcomm_mem_reader.o: labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h
labcomm_mem_writer.o: labcomm_mem_writer.c labcomm_mem_writer.h cppmacros.h
ethaddr.o: ethaddr.c
$(CREATED_DIRS):
mkdir -p $@
run-test: $(TEST_DIR)/test_labcomm_errors |$(TEST_DIR)
test/test_labcomm_errors
$(TEST_DIR)/test_labcomm_errors: $(TEST_DIR)/test_labcomm_errors.o liblabcomm.a |$(TEST_DIR)
$(CC) $(CFLAGS) $(LDFLAGS) -llabcomm -o $@ $^
$(TEST_DIR)/test_labcomm_errors.o: $(TEST_DIR)/test_labcomm_errors.c $(TEST_DIR)/test_labcomm_errors.h |$(TEST_DIR)
cd test; $(CC) $(CFLAGS) -I .. -c $(patsubst $(TEST_DIR)/%, %, $^)
$(TEST_DIR)/test_labcomm.o: $(TEST_DIR)/test_labcomm.c $(TEST_GEN_DIR)/test_sample.h |$(TEST_DIR)
$(CC) -c $(CFLAGS) -o $@ $<
$(TEST_DIR)/test_labcomm: $(TEST_DIR)/test_labcomm.o $(TEST_GEN_DIR)/test_sample.o liblabcomm.a
$(CC) $(CFLAGS) $(LDFLAGS) $(filter-out %.a,$^) $(LDLIBS) $(LDLIBS_TEST) -o $@
$(TEST_GEN_DIR)/%.c $(TEST_GEN_DIR)/%.h: $(TESTDATA_DIR)/%.lc $(LABCOMMC_JAR) |$(TEST_GEN_DIR)
java -jar $(LABCOMMC_JAR) --c=$(patsubst %.h,%.c,$@) --h=$(patsubst %.c,%.h,$@) $<
$(LABCOMMC_JAR):
@echo "======Building LabComm compiler======"
cd $(LABCOMMC_PATH); ant jar
@echo "======End building LabComm compiler======"
%.o: %.c %.h
.PHONY: clean
clean:
$(RM) *.o
$(RM) experimental/*.o experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) $(TEST_DIR)/test_labcomm
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
.PHONY: distclean
distclean:
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
rm -f *.o *.so *.so.1 *.a
distclean: clean
$(RM) liblabcomm.a
#include <errno.h>
#include <string.h>
#ifndef __VXWORKS__
#ifdef ARM_CORTEXM3_CODESOURCERY
#include <string.h>
#else
#include <strings.h>
#endif
#endif
#ifndef ARM_CORTEXM3_CODESOURCERY
#include <stdlib.h>
#endif
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#ifdef __VXWORKS__
#if (CPU == PPC603)
#undef _LITTLE_ENDIAN
#endif
#if (CPU == PENTIUM4)
#undef _BIG_ENDIAN
#endif
#endif
#include "labcomm.h"
#include "labcomm_private.h"
typedef struct labcomm_sample_entry {
struct labcomm_sample_entry *next;
int index;
labcomm_signature_t *signature;
labcomm_decoder_typecast_t decoder;
labcomm_handler_typecast_t handler;
labcomm_encode_typecast_t encode;
void *context;
} labcomm_sample_entry_t;
typedef struct labcomm_encoder_context {
labcomm_sample_entry_t *sample;
int index;
} labcomm_encoder_context_t;
typedef struct labcomm_decoder_context {
labcomm_sample_entry_t *sample;
} labcomm_decoder_context_t;
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback)
{
encoder->on_error = callback;
encoder->writer.on_error = callback;
}
void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback)
{
decoder->on_error = callback;
decoder->reader.on_error = callback;
}
/* Error strings. _must_ be the same order as in enum labcomm_error */
const char *labcomm_error_strings[] = {
"Enum begin guard. DO NO use this as an error.",
"Encoder has no registration for this signature.",
"Encoder is missing do_register",
"Encoder is missing do_encode",
"The labcomm buffer is full and it.",
"Decoder is missing do_register",
"Decoder is missing do_decode_one",
"Decoder: Unknown datatype",
"Decoder: index mismatch",
"Decoder: type not found",
"This function is not yet implemented.",
"User defined error.",
"Could not allocate memory.",
"Enum end guard. DO NO use this as an error."
};
const char *labcomm_error_get_str(enum labcomm_error error_id)
{
const char *error_str = NULL;
// Check if this is a known error ID.
if (error_id >= LABCOMM_ERROR_ENUM_BEGIN_GUARD && error_id <= LABCOMM_ERROR_ENUM_END_GUARD) {
error_str = labcomm_error_strings[error_id];
}
return error_str;
}
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d, labcomm_handle_new_datatype_callback on_new_datatype)
{
d->on_new_datatype = on_new_datatype;
}
int on_new_datatype(labcomm_decoder_t *d, labcomm_signature_t *sig)
{
d->on_error(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE, 4, "%s(): unknown datatype '%s'\n", __FUNCTION__, sig->name);
return 0;
}
void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...)
{
#ifndef LABCOMM_NO_STDIO
const char *err_msg = labcomm_error_get_str(error_id); // The final string to print.
if (err_msg == NULL) {
err_msg = "Error with an unknown error ID occured.";
}
fprintf(stderr, "%s\n", err_msg);
if (nbr_va_args > 0) {
va_list arg_pointer;
va_start(arg_pointer, nbr_va_args);
fprintf(stderr, "%s\n", "Extra info {");
char *print_format = va_arg(arg_pointer, char *);
vfprintf(stderr, print_format, arg_pointer);
fprintf(stderr, "}\n");
va_end(arg_pointer);
}
#else
; // If labcomm can't be compiled with stdio the user will have to make an own error callback functionif he/she needs error reporting.
#endif
}
static labcomm_sample_entry_t *get_sample_by_signature_address(
labcomm_sample_entry_t *head,
labcomm_signature_t *signature)
{
labcomm_sample_entry_t *p;
for (p = head ; p && p->signature != signature ; p = p->next) {
}
return p;
}
static labcomm_sample_entry_t *get_sample_by_signature_value(
labcomm_sample_entry_t *head,
labcomm_signature_t *signature)
{
labcomm_sample_entry_t *p;
for (p = head ; p ; p = p->next) {
if (p->signature->type == signature->type &&
p->signature->size == signature->size &&
strcmp(p->signature->name, signature->name) == 0 &&
bcmp((void*)p->signature->signature, (void*)signature->signature,
signature->size) == 0) {
break;
}
}
return p;
}
static labcomm_sample_entry_t *get_sample_by_index(
labcomm_sample_entry_t *head,
int index)
{
labcomm_sample_entry_t *p;
for (p = head ; p && p->index != index ; p = p->next) {
}
return p;
}
static int get_encoder_index(
labcomm_encoder_t *e,
labcomm_signature_t *s)
{
int result = 0;
labcomm_encoder_context_t *context = e->context;
labcomm_sample_entry_t *sample = context->sample;
while (sample) {
if (sample->signature == s) { break; }
sample = sample->next;
}
if (sample) {
result = sample->index;
}
return result;
}
static void do_encoder_register(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
{
if (signature->type == LABCOMM_SAMPLE) {
if (get_encoder_index(e, signature) == 0) {
int i;
labcomm_encoder_context_t *context = e->context;
labcomm_sample_entry_t *sample =
(labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t));
sample->next = context->sample;
sample->index = context->index;
sample->signature = signature;
sample->encode = encode;
context->index++;
context->sample = sample;
e->writer.write(&e->writer, labcomm_writer_start);
labcomm_encode_int(e, signature->type);
labcomm_encode_type_index(e, signature);
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.data[e->writer.pos] = signature->signature[i];
e->writer.pos++;
}
e->writer.write(&e->writer, labcomm_writer_end);
}
}
}
static void do_encode(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
void *value)
{
labcomm_encoder_context_t *context = encoder->context;
labcomm_sample_entry_t *sample;
sample = get_sample_by_signature_address(context->sample,
signature);
if (sample && sample->encode) {
sample->encode(encoder, value);
} else {
encoder->on_error(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE, 2, "No registration for %s.\n", signature->name);
}
}
labcomm_encoder_t *labcomm_encoder_new(
int (*writer)(labcomm_writer_t *, labcomm_writer_action_t),
void *writer_context)
{
labcomm_encoder_t *result = malloc(sizeof(labcomm_encoder_t));
if (result) {
labcomm_encoder_context_t *context;
context = malloc(sizeof(labcomm_encoder_context_t));
context->sample = NULL;
context->index = LABCOMM_USER;
result->context = context;
result->writer.context = writer_context;
result->writer.data = 0;
result->writer.data_size = 0;
result->writer.count = 0;
result->writer.pos = 0;
result->writer.write = writer;
result->writer.write(&result->writer, labcomm_writer_alloc);
result->writer.on_error = on_error_fprintf;
result->do_register = do_encoder_register;
result->do_encode = do_encode;
result->on_error = on_error_fprintf;
}
return result;
}
void labcomm_internal_encoder_register(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
{
// Will segfault if e == NULL.
if (e->do_register) {
e->do_register(e, signature, encode);
} else {
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_REG, 0);
}
}
void labcomm_internal_encode(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
void *value)
{
// Will segfault if e == NULL
if (e->do_encode) {
e->do_encode(e, signature, value);
} else {
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_ENCODE, 0);
}
}
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);
labcomm_encoder_context_t *econtext = (labcomm_encoder_context_t *) e->context;
labcomm_sample_entry_t *sentry = econtext->sample;
labcomm_sample_entry_t *sentry_next;
while (sentry != NULL) {
sentry_next = sentry->next;
free(sentry);
sentry = sentry_next;
}
free(e->context);
free(e);
}
void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s)
{
int index = get_encoder_index(e, s);
labcomm_encode_int(e, index);
}
static int signature_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);
w->pos = 0;
} break;
case labcomm_writer_start: {
w->data_size = 1000;
w->count = w->data_size;
w->data = realloc(w->data, w->data_size);
w->pos = 0;
} break;
case labcomm_writer_continue: {
w->data_size += 1000;
w->count = w->data_size;
w->data = realloc(w->data, w->data_size);
} break;
case labcomm_writer_end: {
} 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_available: {
} break;
}
return 0;
}
static void collect_flat_signature(
labcomm_decoder_t *decoder,
labcomm_encoder_t *signature_writer)
{
int type = labcomm_decode_int(decoder);
if (type >= LABCOMM_USER) {
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 2, "Implement %s\n", __FUNCTION__);
} else {
labcomm_encode_int(signature_writer, type);
switch (type) {
case LABCOMM_ARRAY: {
int dimensions, i;
dimensions = labcomm_decode_int(decoder);
labcomm_encode_int(signature_writer, dimensions);
for (i = 0 ; i < dimensions ; i++) {
int n = labcomm_decode_int(decoder);
labcomm_encode_int(signature_writer, n);
}
collect_flat_signature(decoder, signature_writer);
} break;
case LABCOMM_STRUCT: {
int fields, i;
fields = labcomm_decode_int(decoder);
labcomm_encode_int(signature_writer, fields);
for (i = 0 ; i < fields ; i++) {
char *name = labcomm_decode_string(decoder);
labcomm_encode_string(signature_writer, name);
free(name);
collect_flat_signature(decoder, signature_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, 2, "Implement %s\n", __FUNCTION__);
} break;
}
}
}
static void do_decoder_register(
labcomm_decoder_t *decoder,
labcomm_signature_t *signature,
labcomm_decoder_typecast_t type_decoder,
labcomm_handler_typecast_t handler,
void *handler_context)
{
labcomm_decoder_context_t *context = decoder->context;
labcomm_sample_entry_t *sample;
sample = get_sample_by_signature_address(context->sample,
signature);
if (!sample) {
sample = (labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t));
sample->next = context->sample;
context->sample = sample;
sample->index = 0;
sample->signature = signature;
}
sample->decoder = type_decoder;
sample->handler = handler;
sample->context = handler_context;
}
static int do_decode_one(labcomm_decoder_t *d)
{
int result;
do {
result = d->reader.read(&d->reader, labcomm_reader_start);
if (result > 0) {
labcomm_decoder_context_t *context = d->context;
result = labcomm_decode_int(d);
if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
labcomm_encoder_t *e = labcomm_encoder_new(signature_writer, 0);
labcomm_signature_t signature;
labcomm_sample_entry_t *entry;
int index;
e->writer.write(&e->writer, labcomm_writer_start);
signature.type = result;
index = labcomm_decode_int(d);
signature.name = labcomm_decode_string(d);
collect_flat_signature(d, e);
signature.size = e->writer.pos;
signature.signature = e->writer.data;
entry = get_sample_by_signature_value(context->sample, &signature);
if (! entry) {
// Unknown datatype, bail out
/*d->on_error(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE, 4, "%s(): unknown datatype '%s' (id=0x%x)\n", __FUNCTION__, signature.name, index);*/
d->on_new_datatype(d, &signature);
} else if (entry->index && entry->index != 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, index);
} else {
// TODO unnessesary, since entry->index == index in above if statement
entry->index = index;
}
free(signature.name);
e->writer.write(&e->writer, labcomm_writer_end);
if (!entry) {
// No handler for found type, bail out (after cleanup)
result = -ENOENT;
}
labcomm_encoder_free(e);
} else {
labcomm_sample_entry_t *entry;
entry = get_sample_by_index(context->sample, result);
if (!entry) {
// printf("Error: %s: type not found (id=0x%x)\n",
//__FUNCTION__, result);
d->on_error(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND, 3, "%s(): type not found (id=0x%x)\n", __FUNCTION__, result);
result = -ENOENT;
} else {
entry->decoder(d, entry->handler, entry->context);
}
}
}
d->reader.read(&d->reader, labcomm_reader_end);
} while (result > 0 && result < LABCOMM_USER);
return result;
}
labcomm_decoder_t *labcomm_decoder_new(
int (*reader)(labcomm_reader_t *, labcomm_reader_action_t),
void *reader_context)
{
labcomm_decoder_t *result = malloc(sizeof(labcomm_decoder_t));
if (result) {
labcomm_decoder_context_t *context =
(labcomm_decoder_context_t*)malloc(sizeof(labcomm_decoder_context_t));
context->sample = 0;
result->context = context;
result->reader.context = reader_context;
result->reader.data = 0;
result->reader.data_size = 0;
result->reader.count = 0;
result->reader.pos = 0;
result->reader.read = reader;
result->reader.read(&result->reader, labcomm_reader_alloc);
result->reader.on_error = on_error_fprintf;
result->do_register = do_decoder_register;
result->do_decode_one = do_decode_one;
result->on_error = on_error_fprintf;
result->on_new_datatype = on_new_datatype;
}
return result;
}
void labcomm_internal_decoder_register(
labcomm_decoder_t *d,
labcomm_signature_t *signature,
labcomm_decoder_typecast_t type_decoder,
labcomm_handler_typecast_t handler,
void *handler_context)
{
// Will segfault if d == NULL
if (d->do_register) {
d->do_register(d, signature, type_decoder, handler, handler_context);
} else {
d->on_error(LABCOMM_ERROR_DEC_MISSING_DO_REG, 0);
}
}
int labcomm_decoder_decode_one(labcomm_decoder_t *d)
{
int result = -1;
// Will segfault if decoder == NULL.
if (d->do_decode_one)
{
result = d->do_decode_one(d);
}
else
{
d->on_error(LABCOMM_ERROR_DEC_MISSING_DO_DECODE_ONE, 0);
}
return result;
}
void labcomm_decoder_run(labcomm_decoder_t *d)
{
while (labcomm_decoder_decode_one(d) > 0) {
}
}
void labcomm_decoder_free(labcomm_decoder_t* d)
{
d->reader.read(&d->reader, labcomm_reader_free);
labcomm_decoder_context_t *context = (labcomm_decoder_context_t *) d->context;
labcomm_sample_entry_t *entry = context->sample;
labcomm_sample_entry_t *entry_next;
while (entry != NULL) {
entry_next = entry->next;
free(entry);
entry = entry_next;
}
free(d->context);
free(d);
}
#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>
/* Forward declaration */
struct labcomm_encoder;
struct labcomm_decoder;
/*
* Signature entry
*/
typedef struct {
int type;
char *name;
int (*encoded_size)(void *);
int size;
unsigned char *signature;
} labcomm_signature_t;
/*
* Error handling.
*/
/* Error IDs */
enum labcomm_error {
LABCOMM_ERROR_ENUM_BEGIN_GUARD, // _must_ be the first enum element. labcomm_error_get_str() depends on this.
LABCOMM_ERROR_ENC_NO_REG_SIGNATURE,
LABCOMM_ERROR_ENC_MISSING_DO_REG,
LABCOMM_ERROR_ENC_MISSING_DO_ENCODE,
LABCOMM_ERROR_ENC_BUF_FULL,
LABCOMM_ERROR_DEC_MISSING_DO_REG,
LABCOMM_ERROR_DEC_MISSING_DO_DECODE_ONE,
LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE,
LABCOMM_ERROR_DEC_INDEX_MISMATCH,
LABCOMM_ERROR_DEC_TYPE_NOT_FOUND,
LABCOMM_ERROR_UNIMPLEMENTED_FUNC,
LABCOMM_ERROR_MEMORY,
LABCOMM_ERROR_USER_DEF,
LABCOMM_ERROR_ENUM_END_GUARD // _must_ be the last enum element. labcomm_error_get_str() depends on this.
};
/* Error strings. _must_ be the same order as in enum labcomm_error */
extern const char *labcomm_error_strings[];
/* The callback prototype for error handling.\
* First parameter is the error ID.
* The second paramters is the number of va_args that comes after this one. If noneit should be 0.
* Optionaly other paramters can be supplied depending on what is needed for this error ID.
*/
typedef void (* labcomm_error_handler_callback)(enum labcomm_error error_id, size_t nbr_va_args, ...);
/* Default error handler, prints message to stderr.
* Extra info about the error can be supplied as char* as VA-args. Especially user defined errors should supply a describing string. if nbr_va_args > 1 the first variable argument must be a printf format string and the possibly following arguments are passed as va_args to vprintf.
*/
void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...);
/* Register a callback for the error handler for this encoder. */
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback);
/* Register a callback for the error handler for this decoder. */
void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback);
/* Get a string describing the supplied standrad labcomm error. */
const char *labcomm_error_get_str(enum labcomm_error error_id);
typedef int (* labcomm_handle_new_datatype_callback)(struct labcomm_decoder *decoder,
labcomm_signature_t *sig);
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
labcomm_handle_new_datatype_callback on_new_datatype);
/*
* Decoder
*/
typedef enum {
labcomm_reader_alloc,
labcomm_reader_free,
labcomm_reader_start,
labcomm_reader_continue,
labcomm_reader_end
} labcomm_reader_action_t;
typedef struct labcomm_reader {
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int (*read)(struct labcomm_reader *, labcomm_reader_action_t);
labcomm_error_handler_callback on_error;
} labcomm_reader_t;
struct labcomm_decoder *labcomm_decoder_new(
int (*reader)(labcomm_reader_t *, labcomm_reader_action_t),
void *reader_context);
int labcomm_decoder_decode_one(
struct labcomm_decoder *decoder);
void labcomm_decoder_run(
struct labcomm_decoder *decoder);
void labcomm_decoder_free(
struct labcomm_decoder *decoder);
/*
* Encoder
*/
typedef enum {
labcomm_writer_alloc,
labcomm_writer_free,
labcomm_writer_start,
labcomm_writer_continue,
labcomm_writer_end,
labcomm_writer_available,
} labcomm_writer_action_t;
typedef struct labcomm_writer {
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int (*write)(struct labcomm_writer *, labcomm_writer_action_t);
labcomm_error_handler_callback on_error;
} labcomm_writer_t;
struct labcomm_encoder *labcomm_encoder_new(
int (*writer)(labcomm_writer_t *, labcomm_writer_action_t),
void *writer_context);
void labcomm_encoder_free(
struct labcomm_encoder *encoder);
#endif
#include <errno.h>
#include <unistd.h>
#include "labcomm.h"
#define BUFFER_SIZE 2048
int labcomm_fd_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action)
{
int result = -EINVAL;
int *fd = r->context;
switch (action) {
case labcomm_reader_alloc: {
r->data = malloc(BUFFER_SIZE);
if (r->data) {
r->data_size = BUFFER_SIZE;
result = r->data_size;
} else {
r->data_size = 0;
result = -ENOMEM;
}
r->count = 0;
r->pos = 0;
} break;
case labcomm_reader_start:
case labcomm_reader_continue: {
if (r->pos < r->count) {
result = r->count - r->pos;
} else {
int err;
r->pos = 0;
err = read(*fd, r->data, r->data_size);
if (err <= 0) {
r->count = 0;
result = -1;
} else {
r->count = err;
result = r->count - r->pos;
}
}
} break;
case labcomm_reader_end: {
result = 0;
} break;
case labcomm_reader_free: {
free(r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
result = 0;
} break;
}
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: {
w->pos = 0;
} break;
case labcomm_writer_continue: {
result = write(*fd, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_end: {
result = write(*fd, w->data, w->pos);
w->pos = 0;
} break;
case labcomm_writer_available: {
result = w->count - w->pos;
} break;
}
return result;
}
#include "labcomm.h"
extern int labcomm_fd_reader(
labcomm_reader_t *r,
labcomm_reader_action_t action);
extern int labcomm_fd_writer(
labcomm_writer_t *r,
labcomm_writer_action_t action);
#ifndef _LABCOMM_PRIVATE_H_
#define _LABCOMM_PRIVATE_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 "labcomm.h"
/*
* Predeclared aggregate type indices
*/
#define LABCOMM_TYPEDEF 0x01
#define LABCOMM_SAMPLE 0x02
#define LABCOMM_ARRAY 0x10
#define LABCOMM_STRUCT 0x11
/*
* Predeclared primitive type indices
*/
#define LABCOMM_BOOLEAN 0x20
#define LABCOMM_BYTE 0x21
#define LABCOMM_SHORT 0x22
#define LABCOMM_INT 0x23
#define LABCOMM_LONG 0x24
#define LABCOMM_FLOAT 0x25
#define LABCOMM_DOUBLE 0x26
#define LABCOMM_STRING 0x27
/*
* Start index for user defined types
*/
#define LABCOMM_USER 0x80
/*
* Semi private decoder declarations
*/
typedef void (*labcomm_handler_typecast_t)(void *, void *);
typedef void (*labcomm_decoder_typecast_t)(
struct labcomm_decoder *,
labcomm_handler_typecast_t,
void *);
typedef struct labcomm_decoder {
void *context;
labcomm_reader_t reader;
void (*do_register)(struct labcomm_decoder *,
labcomm_signature_t *,
labcomm_decoder_typecast_t,
labcomm_handler_typecast_t,
void *context);
int (*do_decode_one)(struct labcomm_decoder *decoder);
labcomm_error_handler_callback on_error;
labcomm_handle_new_datatype_callback on_new_datatype;
} labcomm_decoder_t;
/*
* Non typesafe registration function to be called from
* generated labcomm_decoder_register_* functions.
*/
void labcomm_internal_decoder_register(
labcomm_decoder_t *,
labcomm_signature_t *,
labcomm_decoder_typecast_t,
labcomm_handler_typecast_t,
void *context);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(labcomm_reader_t *r) { \
type result; int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (r->pos >= r->count) { \
r->read(r, labcomm_reader_continue); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
} \
static inline type labcomm_decode_##name(labcomm_decoder_t *d) { \
return labcomm_read_##name(&d->reader); \
}
#else
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(labcomm_reader_t *r) { \
type result; int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (r->pos >= r->count) { \
r->read(r, labcomm_reader_continue); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
} \
static inline type labcomm_decode_##name(labcomm_decoder_t *d) { \
return labcomm_read_##name(&d->reader); \
}
#endif
LABCOMM_DECODE(boolean, unsigned char)
LABCOMM_DECODE(byte, unsigned char)
LABCOMM_DECODE(short, short)
LABCOMM_DECODE(int, int)
LABCOMM_DECODE(long, long long)
LABCOMM_DECODE(float, float)
LABCOMM_DECODE(double, double)
static inline char *labcomm_read_string(labcomm_reader_t *r)
{
char *result;
int length, i;
length = labcomm_read_int(r);
result = malloc(length + 1);
for (i = 0 ; i < length ; i++) {
if (r->pos >= r->count) {
r->read(r, labcomm_reader_continue);
}
result[i] = r->data[r->pos];
r->pos++;
}
result[length] = 0;
return result;
}
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 errer flag
r->data = data;
r->data_size = length;
r->count = length;
r->pos = 0;
r->read = labcomm_buffer_read;
}
/*
* Semi private encoder declarations
*/
typedef void (*labcomm_encode_typecast_t)(
struct labcomm_encoder *,
void *value);
typedef struct labcomm_encoder {
void *context;
labcomm_writer_t writer;
void (*do_register)(struct labcomm_encoder *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t);
void (*do_encode)(struct labcomm_encoder *encoder,
labcomm_signature_t *signature,
void *value);
labcomm_error_handler_callback on_error;
} labcomm_encoder_t;
void labcomm_internal_encoder_register(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode);
void labcomm_internal_encode(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
void *value);
#define LABCOMM_USER_ACTION(i) (i + 100)
void labcomm_internal_encoder_user_action(struct labcomm_encoder *encoder,
int action);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_ENCODE(name, type) \
static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \
int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (w->pos >= w->count) { /*buffer is full*/ \
w->write(w, labcomm_writer_continue); \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
} \
static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
labcomm_write_##name(&e->writer, data); \
}
#else
#define LABCOMM_ENCODE(name, type) \
static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \
int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (w->pos >= w->count) { \
w->write(w, labcomm_writer_continue); \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
} \
static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
labcomm_write_##name(&e->writer, data); \
}
#endif
LABCOMM_ENCODE(boolean, unsigned char)
LABCOMM_ENCODE(byte, unsigned char)
LABCOMM_ENCODE(short, short)
LABCOMM_ENCODE(int, int)
LABCOMM_ENCODE(long, long long)
LABCOMM_ENCODE(float, float)
LABCOMM_ENCODE(double, double)
static inline void labcomm_write_string(labcomm_writer_t *w, char *s)
{
int length, i;
length = strlen((char*)s);
labcomm_write_int(w, length);
for (i = 0 ; i < length ; i++) {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
}
w->data[w->pos] = s[i];
w->pos++;
}
}
static inline void labcomm_encode_string(labcomm_encoder_t *e,
char *s)
{
labcomm_write_string(&e->writer, s);
}
void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s);
static inline int labcomm_buffer_write(struct labcomm_writer *w,
labcomm_writer_action_t action)
{
// If this gets called, it is an error,
// so note error and let producer proceed
w->context = w;
w->pos = 0;
return 0;
}
static inline int labcomm_buffer_writer_error(struct labcomm_writer *w)
{
return w->context != NULL;
}
static inline void labcomm_buffer_writer_setup(struct labcomm_writer *w,
void *data,
int length)
{
w->context = NULL; // Used as error flag
w->data = data;
w->data_size = length;
w->count = length;
w->pos = 0;
w->write = labcomm_buffer_write;
}
#endif
## 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 <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();
}
File deleted
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=Constant\
Decoder \
DecoderChannel \
DecoderRegistry \
Encoder \
EncoderChannel \
EncoderRegistry \
RenamingDecoder \
RenamingEncoder \
RenamingRegistry \
Sample \
SampleDispatcher \
SampleHandler \
SampleType \
WrappingDecoder \
WrappingEncoder
.PHONY: all
all: labcomm2014.dll
labcomm2014.dll: $(MODULES:%=se/lth/control/labcomm2014/%.cs) Makefile
mcs -out:$@ -target:library $(filter %.cs, $^)
.PHONY: test
test:
.PHONY: clean
clean:
.PHONY: distclean
distclean:
rm -f labcomm2014.dll
namespace se.lth.control.labcomm {
public interface LabCommHandler {
}
}
\ No newline at end of file
public interface LabCommSample {
}
namespace se.lth.control.labcomm {
namespace se.lth.control.labcomm2014 {
public class LabComm {
public class Constant {
public const string CURRENT_VERSION = "LabComm2014";
/*
* 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 */
/*
* Predeclared aggregate type indices
* Predefined aggregate type indices
*/
public const int TYPEDEF = 0x01;
public const int SAMPLE = 0x02;
public const int ARRAY = 0x10;
public const int STRUCT = 0x11;
......@@ -21,11 +32,7 @@ namespace se.lth.control.labcomm {
public const int FLOAT = 0x25;
public const int DOUBLE = 0x26;
public const int STRING = 0x27;
/*
* start of user defined types
*/
public const int FIRST_USER_INDEX = 0x80;
public const int SAMPLE = 0x28;
}
......