diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 0000000000000000000000000000000000000000..9aefbbac4a1b145311f9bd884612d08335e98465 --- /dev/null +++ b/.bzrignore @@ -0,0 +1,19 @@ +AST +AST/* +LabComm.class +labComm.jar +lib/java/se/lth/control/labcomm/LabComm.class +lib/java/se/lth/control/labcomm/LabCommDecoderChannel.class +lib/java/se/lth/control/labcomm/LabCommDecoder.class +lib/java/se/lth/control/labcomm/LabCommDecoderRegistry.class +lib/java/se/lth/control/labcomm/LabCommDecoderRegistry$Entry.class +lib/java/se/lth/control/labcomm/LabCommDispatcher.class +lib/java/se/lth/control/labcomm/LabCommEncoderChannel.class +lib/java/se/lth/control/labcomm/LabCommEncoder.class +lib/java/se/lth/control/labcomm/LabCommEncoderRegistry.class +lib/java/se/lth/control/labcomm/LabCommEncoderRegistry$Entry.class +lib/java/se/lth/control/labcomm/LabCommHandler.class +lib/java/se/lth/control/labcomm/LabCommReader.class +lib/java/se/lth/control/labcomm/LabCommSample.class +lib/java/se/lth/control/labcomm/LabCommType.class +lib/java/se/lth/control/labcomm/LabCommWriter.class diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c new file mode 100644 index 0000000000000000000000000000000000000000..ee93aec315e0dfc0f097e07119abfa5a11edd651 --- /dev/null +++ b/lib/c/labcomm.c @@ -0,0 +1,437 @@ +#include <errno.h> +#include <string.h> +#include <stdio.h> +#ifndef __VXWORKS__ +#include <strings.h> +#endif +#include <stdlib.h> +#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; + +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 { + printf("Encoder has 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 = 0; + 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->do_register = do_encoder_register; + result->do_encode = do_encode; + } + return result; +} + +void labcomm_internal_encoder_register( + labcomm_encoder_t *e, + labcomm_signature_t *signature, + labcomm_encode_typecast_t encode) +{ + if (e && e->do_register) { + e->do_register(e, signature, encode); + } else { + printf("Encoder is missing do_register\n"); + } +} + +void labcomm_internal_encode( + labcomm_encoder_t *e, + labcomm_signature_t *signature, + void *value) +{ + if (e && e->do_encode) { + e->do_encode(e, signature, value); + } else { + printf("Encoder is missing do_encode\n"); + } +} + +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); + 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) { + printf("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: { + printf("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 + fprintf(stderr, "%s: unknown datatype '%s' (id=0x%x)\n", + __FUNCTION__, signature.name, index); + } else if (entry->index && entry->index != index) { + fprintf(stderr, "%s: index mismatch '%s' (id=0x%x != 0x%x)\n", + __FUNCTION__, signature.name, entry->index, index); + } else { + 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) { + fprintf(stderr, "%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->do_register = do_decoder_register; + result->do_decode_one = do_decode_one; + } + 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) +{ + if (d && d->do_register) { + d->do_register(d, signature, type_decoder, handler, handler_context); + } else { + printf("Decoder is missing do_register\n"); + } +} + +int labcomm_decoder_decode_one(labcomm_decoder_t *d) +{ + int result = -1; + if (d && d->do_decode_one) { + result = d->do_decode_one(d); + } else { + printf("Decoder is missing do_decode_one\n"); + } + 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); + free(d); +} diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h new file mode 100644 index 0000000000000000000000000000000000000000..9fed6976f1d5760b60b36213578e70d4ab89d2ce --- /dev/null +++ b/lib/c/labcomm.h @@ -0,0 +1,83 @@ +#ifndef _LABCOMM_H_ +#define _LABCOMM_H_ + +#include <endian.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * Signature entry + */ +typedef struct { + int type; + char *name; + int (*encoded_size)(void *); + int size; + unsigned char *signature; +} labcomm_signature_t; + + +/* + * Decoder + */ +struct labcomm_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_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 + */ +struct labcomm_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_writer_t; + +struct labcomm_encoder; +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 diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h new file mode 100644 index 0000000000000000000000000000000000000000..3bc5140640f9a2b473ce3cd887764fdc1807b03f --- /dev/null +++ b/lib/c/labcomm_private.h @@ -0,0 +1,290 @@ +#ifndef _LABCOMM_PRIVATE_H_ +#define _LABCOMM_PRIVATE_H_ + +#include <endian.h> +#include <stdio.h> +#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_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_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) { \ + 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