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 134 additions and 1862 deletions
/*
labcomm.c -- runtime for handling encoding and decoding of
labcomm samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This program 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.
This program 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/>.
*/
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <stdio.h>
#include <strings.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include "labcomm.h"
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
#define LABCOMM_VERSION "LabComm2013"
struct labcomm_decoder {
void *context;
struct labcomm_reader reader;
struct {
void *context;
const struct labcomm_lock_action *action;
} lock;
labcomm_error_handler_callback on_error;
labcomm_handle_new_datatype_callback on_new_datatype;
};
struct labcomm_encoder {
void *context;
struct labcomm_writer writer;
struct {
void *context;
const struct labcomm_lock_action *action;
} lock;
labcomm_error_handler_callback on_error;
};
struct labcomm_sample_entry {
struct labcomm_sample_entry *next;
int index;
struct labcomm_signature *signature;
labcomm_decoder_function decoder;
labcomm_handler_function handler;
labcomm_encoder_function encode;
void *context;
};
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
extern struct labcomm_signature labcomm_first_signature;
extern struct labcomm_signature labcomm_last_signature;
#endif
struct labcomm_encoder_context {
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
struct labcomm_sample_entry *sample;
int index;
#else
struct labcomm_sample_entry *by_section;
#endif
};
struct labcomm_decoder_context {
struct labcomm_sample_entry *sample;
};
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(struct labcomm_decoder *d, struct labcomm_signature *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 struct labcomm_sample_entry *get_sample_by_signature_address(
struct labcomm_sample_entry *head,
struct labcomm_signature *signature)
{
struct labcomm_sample_entry *p;
for (p = head ; p && p->signature != signature ; p = p->next) {
}
return p;
}
static struct labcomm_sample_entry *get_sample_by_signature_value(
struct labcomm_sample_entry *head,
struct labcomm_signature *signature)
{
struct labcomm_sample_entry *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 struct labcomm_sample_entry *get_sample_by_index(
struct labcomm_sample_entry *head,
int index)
{
struct labcomm_sample_entry *p;
for (p = head ; p && p->index != index ; p = p->next) {
}
return p;
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int get_encoder_index_by_search(
struct labcomm_encoder *e,
struct labcomm_signature *s)
{
int result = 0;
struct labcomm_encoder_context *context = e->context;
struct labcomm_sample_entry *sample = context->sample;
while (sample) {
if (sample->signature == s) { break; }
sample = sample->next;
}
if (sample) {
result = sample->index;
}
return result;
}
#else
static int get_encoder_index_by_section(
struct labcomm_encoder *e,
struct labcomm_signature *s)
{
int result = -ENOENT;
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
//fprintf(stderr, "%d\n", (int)(s - &labcomm_start));
result = s - &labcomm_first_signature + LABCOMM_USER;
}
return result;
}
#endif
static int get_encoder_index(
struct labcomm_encoder *e,
struct labcomm_signature *s)
{
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
return get_encoder_index_by_search(e, s);
#else
return get_encoder_index_by_section(e, s);
#endif
}
static void labcomm_encode_signature(struct labcomm_encoder *e,
struct labcomm_signature *signature)
{
int i, index;
index = get_encoder_index(e, signature);
e->writer.action.start(&e->writer, e, index, signature, NULL);
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) {
e->writer.action.flush(&e->writer);
}
e->writer.data[e->writer.pos] = signature->signature[i];
e->writer.pos++;
}
e->writer.action.end(&e->writer);
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int encoder_add_signature_by_search(struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
int result;
struct labcomm_encoder_context *context = e->context;
struct labcomm_sample_entry *sample;
sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample));
if (sample == NULL) {
result = -ENOMEM;
} else {
sample->next = context->sample;
sample->index = context->index;
sample->signature = signature;
sample->encode = encode;
context->index++;
context->sample = sample;
result = sample->index;
}
return result;
}
#endif
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
static int encoder_add_signature_by_section(struct labcomm_encoder *e,
struct labcomm_signature *s,
labcomm_encoder_function encode)
{
int result = -ENOENT;
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
/* Signature is in right linker section */
struct labcomm_encoder_context *context = e->context;
int index = s - &labcomm_first_signature;
if (context->by_section == NULL) {
int n = &labcomm_last_signature - &labcomm_first_signature;
context->by_section = malloc(n * sizeof(context->by_section[0]));
}
if (context->by_section == NULL) {
result = -ENOMEM;
goto out;
}
context->by_section[index].next = NULL;
context->by_section[index].index = index + LABCOMM_USER;
context->by_section[index].signature = s;
context->by_section[index].encode = encode;
result = context->by_section[index].index;
}
out:
return result;
}
#endif
static int encoder_add_signature(struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
int index = -ENOENT;
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
index = encoder_add_signature_by_search(e, signature, encode);
#else
index = encoder_add_signature_by_section(e, signature, encode);
#endif
return index;
}
/*
static struct labcomm_sample_entry *encoder_get_sample_by_signature_address(
struct labcomm_encoder *encoder,
struct labcomm_signature *s)
{
struct labcomm_sample_entry *result = NULL;
struct labcomm_encoder_context *context = encoder->context;
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
result = &context->by_section[s - &labcomm_first_signature];
}
#else
result = get_sample_by_signature_address(context->sample, s);
#endif
return result;
}
*/
struct labcomm_encoder *labcomm_encoder_new(
const struct labcomm_writer_action writer,
void *writer_context,
const struct labcomm_lock_action *lock,
void *lock_context)
{
struct labcomm_encoder *result = malloc(sizeof(*result));
if (result) {
struct labcomm_encoder_context *context;
context = malloc(sizeof(*context));
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
context->sample = NULL;
context->index = LABCOMM_USER;
#else
context->by_section = NULL;
#endif
result->context = context;
result->writer.data = 0;
result->writer.data_size = 0;
result->writer.count = 0;
result->writer.pos = 0;
result->writer.error = 0;
result->writer.action = writer;
result->writer.context = writer_context;
result->lock.action = lock;
result->lock.context = lock_context;
result->writer.on_error = on_error_fprintf;
result->on_error = on_error_fprintf;
result->writer.action.alloc(&result->writer, LABCOMM_VERSION);
}
return result;
}
void labcomm_internal_encoder_register(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
if (signature->type == LABCOMM_SAMPLE) {
if (get_encoder_index(e, signature) == 0) {
int index = encoder_add_signature(e, signature, encode);
if (index > 0) {
struct labcomm_ioctl_register_signature ioctl_data;
int err;
ioctl_data.index = index;
ioctl_data.signature = signature;
err = labcomm_encoder_ioctl(e, LABCOMM_IOCTL_REGISTER_SIGNATURE,
&ioctl_data);
if (err != 0) {
labcomm_encode_signature(e, signature);
}
}
}
}
}
int labcomm_internal_encode(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode,
void *value)
{
int result;
int index;
index = get_encoder_index(e, signature);
result = e->writer.action.start(&e->writer, e, index, signature, value);
if (result == -EALREADY) { result = 0; goto no_end; }
if (result != 0) { goto out; }
result = labcomm_write_packed32(&e->writer, index);
if (result != 0) { goto out; }
result = encode(&e->writer, value);
out:
e->writer.action.end(&e->writer);
no_end:
return result;
}
void labcomm_encoder_free(struct labcomm_encoder* e)
{
e->writer.action.free(&e->writer);
struct labcomm_encoder_context *context = (struct labcomm_encoder_context *) e->context;
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
struct labcomm_sample_entry *entry = context->sample;
struct labcomm_sample_entry *entry_next;
while (entry != NULL) {
entry_next = entry->next;
free(entry);
entry = entry_next;
}
#else
free(context->by_section);
#endif
free(e->context);
free(e);
}
int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
int action,
...)
{
int result = -ENOTSUP;
if (encoder->writer.action.ioctl != NULL) {
va_list va;
va_start(va, action);
result = encoder->writer.action.ioctl(&encoder->writer, action, NULL, va);
va_end(va);
}
return result;
}
static int labcomm_writer_ioctl(struct labcomm_writer *writer,
int action,
...)
{
int result = -ENOTSUP;
if (writer->action.ioctl != NULL) {
va_list va;
va_start(va, action);
result = writer->action.ioctl(writer, action, NULL, va);
va_end(va);
}
return result;
}
int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
int action,
struct labcomm_signature *signature,
va_list va)
{
int result = -ENOTSUP;
if (encoder->writer.action.ioctl != NULL) {
result = encoder->writer.action.ioctl(&encoder->writer, action,
signature, va);
}
return result;
}
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);
free(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;
}
}
}
struct labcomm_decoder *labcomm_decoder_new(
const struct labcomm_reader_action reader,
void *reader_context,
const struct labcomm_lock_action *lock,
void *lock_context)
{
struct labcomm_decoder *result = malloc(sizeof(*result));
if (result) {
struct labcomm_decoder_context *context =
(struct labcomm_decoder_context *)malloc(sizeof(*context));
context->sample = 0;
result->context = context;
result->reader.data = 0;
result->reader.data_size = 0;
result->reader.count = 0;
result->reader.pos = 0;
result->reader.action = reader;
result->reader.context = reader_context;
result->reader.on_error = on_error_fprintf;
result->lock.action = lock;
result->lock.context = lock_context;
result->on_error = on_error_fprintf;
result->on_new_datatype = on_new_datatype;
result->reader.action.alloc(&result->reader, LABCOMM_VERSION);
}
return result;
}
void labcomm_internal_decoder_register(
struct labcomm_decoder *d,
struct labcomm_signature *signature,
labcomm_decoder_function type_decoder,
labcomm_handler_function handler,
void *handler_context)
{
struct labcomm_decoder_context *context = d->context;
struct labcomm_sample_entry *sample;
sample = get_sample_by_signature_address(context->sample,
signature);
if (!sample) {
sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample));
sample->next = context->sample;
context->sample = sample;
sample->index = 0;
sample->signature = signature;
}
sample->decoder = type_decoder;
sample->handler = handler;
sample->context = handler_context;
}
int labcomm_decoder_decode_one(struct labcomm_decoder *d)
{
int result;
do {
result = d->reader.action.start(&d->reader);
if (result > 0) {
struct labcomm_decoder_context *context = d->context;
result = labcomm_read_packed32(&d->reader);
if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
/* TODO: should the labcomm_dynamic_buffer_writer be
a permanent part of labcomm_decoder? */
struct labcomm_writer writer = {
.context = NULL,
.data = NULL,
.data_size = 0,
.count = 0,
.pos = 0,
.error = 0,
.action = labcomm_dynamic_buffer_writer,
.on_error = NULL
};
struct labcomm_signature signature;
struct labcomm_sample_entry *entry = NULL;
int index, err;
writer.action.alloc(&writer, "");
writer.action.start(&writer, NULL, 0, NULL, NULL);
index = labcomm_read_packed32(&d->reader); //int
signature.name = labcomm_read_string(&d->reader);
signature.type = result;
collect_flat_signature(d, &writer);
writer.action.end(&writer);
err = labcomm_writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&signature.size);
if (err < 0) {
printf("Failed to get size: %s\n", strerror(-err));
goto free_signature_name;
}
err = labcomm_writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
&signature.signature);
if (err < 0) {
printf("Failed to get pointer: %s\n", strerror(-err));
goto free_signature_name;
}
entry = get_sample_by_signature_value(context->sample, &signature);
if (! entry) {
/* Unknown datatype, bail out */
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:
free(signature.name);
writer.action.free(&writer);
if (!entry) {
// No handler for found type, bail out (after cleanup)
result = -ENOENT;
}
} else {
struct labcomm_sample_entry *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->reader, entry->handler, entry->context);
}
}
}
d->reader.action.end(&d->reader);
/* TODO: should we really loop, or is it OK to
return after a typedef/sample */
} while (result > 0 && result < LABCOMM_USER);
return result;
}
void labcomm_decoder_run(struct labcomm_decoder *d)
{
while (labcomm_decoder_decode_one(d) > 0) {
}
}
void labcomm_decoder_free(struct labcomm_decoder* d)
{
d->reader.action.free(&d->reader);
struct labcomm_decoder_context *context = (struct labcomm_decoder_context *) d->context;
struct labcomm_sample_entry *entry = context->sample;
struct labcomm_sample_entry *entry_next;
while (entry != NULL) {
entry_next = entry->next;
free(entry);
entry = entry_next;
}
free(d->context);
free(d);
}
int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
int action,
...)
{
int result = -ENOTSUP;
if (decoder->reader.action.ioctl != NULL) {
va_list va;
va_start(va, action);
result = decoder->reader.action.ioctl(&decoder->reader, action, NULL, va);
va_end(va);
}
return result;
}
int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
int action,
struct labcomm_signature *signature,
va_list va)
{
int result = -ENOTSUP;
if (decoder->reader.action.ioctl != NULL) {
result = decoder->reader.action.ioctl(&decoder->reader, action, NULL, va);
}
return result;
}
#ifndef _LABCOMM_H_
#define _LABCOMM_H_
#include <stdarg.h>
#include <unistd.h>
/* Forward declaration */
struct labcomm_encoder;
struct labcomm_decoder;
/*
* Signature entry
*/
struct labcomm_signature {
int type;
char *name;
int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample *
int size;
unsigned char *signature;
int cached_encoded_size; // -1 if not initialized or type is variable size
};
/*
* 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 none it 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,
struct labcomm_signature *sig);
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
labcomm_handle_new_datatype_callback on_new_datatype);
/*
* Locking support (optional)
*/
struct labcomm_lock_action {
int (*alloc)(void *context);
int (*free)(void *context);
int (*read_lock)(void *context);
int (*read_unlock)(void *context);
int (*write_lock)(void *context);
int (*write_unlock)(void *context);
};
/*
* Decoder
*/
struct labcomm_reader;
struct labcomm_reader_action {
int (*alloc)(struct labcomm_reader *r, char *labcomm_version);
int (*free)(struct labcomm_reader *r);
int (*start)(struct labcomm_reader *r);
int (*end)(struct labcomm_reader *r);
int (*fill)(struct labcomm_reader *r);
int (*ioctl)(struct labcomm_reader *r, int, struct labcomm_signature *, va_list);
};
struct labcomm_reader {
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int error;
struct labcomm_reader_action action;
labcomm_error_handler_callback on_error;
};
struct labcomm_decoder *labcomm_decoder_new(
const struct labcomm_reader_action reader,
void *reader_context,
const struct labcomm_lock_action *lock,
void *lock_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);
/* See labcomm_ioctl.h for predefined ioctl_action values */
int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
int ioctl_action,
...);
/*
* Encoder
*/
struct labcomm_writer;
struct labcomm_writer_action {
int (*alloc)(struct labcomm_writer *w, char *labcomm_version);
int (*free)(struct labcomm_writer *w);
int (*start)(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index, struct labcomm_signature *signature,
void *value);
int (*end)(struct labcomm_writer *w);
int (*flush)(struct labcomm_writer *w);
int (*ioctl)(struct labcomm_writer *w,
int index, struct labcomm_signature *,
va_list);
};
struct labcomm_writer {
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int error;
struct labcomm_writer_action action;
labcomm_error_handler_callback on_error;
};
struct labcomm_encoder *labcomm_encoder_new(
const struct labcomm_writer_action writer,
void *writer_context,
const struct labcomm_lock_action *lock,
void *lock_context);
void labcomm_encoder_free(
struct labcomm_encoder *encoder);
/* See labcomm_ioctl.h for predefined ioctl_action values */
int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
int ioctl_action,
...);
#endif
SECTIONS {
labcomm : {
labcomm_first_signature = ABSOLUTE(.) ;
*(labcomm)
labcomm_last_signature = ABSOLUTE(.) ;
}
}
INSERT AFTER .data;
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
static int dyn_alloc(struct labcomm_writer *w, char *labcomm_version)
{
w->data_size = 1000;
w->count = w->data_size;
w->data = malloc(w->data_size);
if (w->data == NULL) {
w->error = -ENOMEM;
}
w->pos = 0;
return w->error;
}
static int dyn_free(struct labcomm_writer *w)
{
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
return 0;
}
static int dyn_start(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
struct labcomm_signature *signature,
void *value)
{
void *tmp;
w->data_size = 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
w->error = 0;
} else {
w->error = -ENOMEM;
}
w->pos = 0;
return w->error;
}
static int dyn_end(struct labcomm_writer *w)
{
return 0;
}
static int dyn_flush(struct labcomm_writer *w)
{
void *tmp;
w->data_size += 1000;
w->count = w->data_size;
tmp = realloc(w->data, w->data_size);
if (tmp != NULL) {
w->data = tmp;
w->error = 0;
} else {
w->error = -ENOMEM;
}
return w->error;
}
static int dyn_ioctl(struct labcomm_writer *w,
int action,
struct labcomm_signature *signature,
va_list arg)
{
int result = -ENOTSUP;
switch (action) {
case LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN: {
int *value = va_arg(arg, int*);
*value = w->pos;
result = 0;
} break;
case LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER: {
void **value = va_arg(arg, void**);
*value = w->data;
result = 0;
} break;
}
return result;
}
const struct labcomm_writer_action labcomm_dynamic_buffer_writer = {
.alloc = dyn_alloc,
.free = dyn_free,
.start = dyn_start,
.end = dyn_end,
.flush = dyn_flush,
.ioctl = dyn_ioctl
};
#ifndef _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
#define _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
#include "labcomm.h"
extern const struct labcomm_writer_action labcomm_dynamic_buffer_writer;
#endif
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm_private.h"
#include "labcomm_fd_reader.h"
#define BUFFER_SIZE 2048
static int fd_alloc(struct labcomm_reader *r, char *version)
{
int result = 0;
r->count = 0;
r->pos = 0;
r->data = malloc(BUFFER_SIZE);
if (! r->data) {
r->data_size = 0;
result = -ENOMEM;
} else {
char *tmp;
r->data_size = BUFFER_SIZE;
tmp = labcomm_read_string(r);
if (strcmp(tmp, version) != 0) {
result = -EINVAL;
} else {
result = r->data_size;
}
free(tmp);
}
return result;
}
static int fd_free(struct labcomm_reader *r)
{
free(r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
return 0;
}
static int fd_fill(struct labcomm_reader *r)
{
int result = 0;
int *fd = r->context;
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 = -EPIPE;
} else {
r->count = err;
result = r->count - r->pos;
}
}
return result;
}
static int fd_start(struct labcomm_reader *r)
{
return fd_fill(r);
}
static int fd_end(struct labcomm_reader *r)
{
return 0;
}
const struct labcomm_reader_action labcomm_fd_reader = {
.alloc = fd_alloc,
.free = fd_free,
.start = fd_start,
.fill = fd_fill,
.end = fd_end,
.ioctl = NULL
};
#ifndef _LABCOMM_FD_READER_H_
#define _LABCOMM_FD_READER_H_
#include "labcomm.h"
extern const struct labcomm_reader_action labcomm_fd_reader;
#endif
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "labcomm_private.h"
#include "labcomm_fd_writer.h"
#define BUFFER_SIZE 2048
static int fd_flush(struct labcomm_writer *w);
static int fd_alloc(struct labcomm_writer *w, char *version)
{
w->data = malloc(BUFFER_SIZE);
if (! w->data) {
w->error = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} else {
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
labcomm_write_string(w, version);
fd_flush(w);
}
return w->error;
}
static int fd_free(struct labcomm_writer *w)
{
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
return 0;
}
static int fd_start(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
struct labcomm_signature *signature,
void *value)
{
w->pos = 0;
return w->error;
}
static int fd_flush(struct labcomm_writer *w)
{
int *fd = w->context;
int err;
err = write(*fd, w->data, w->pos);
if (err < 0) {
w->error = -errno;
} else if (err == 0) {
w->error = -EINVAL;
}
w->pos = 0;
return w->error;
}
const struct labcomm_writer_action labcomm_fd_writer = {
.alloc = fd_alloc,
.free = fd_free,
.start = fd_start,
.end = fd_flush,
.flush = fd_flush,
.ioctl = NULL
};
#ifndef _LABCOMM_FD_WRITER_H_
#define _LABCOMM_FD_WRITER_H_
#include "labcomm.h"
extern const struct labcomm_writer_action labcomm_fd_writer;
#endif
#include "labcomm.h"
struct labcomm_ioctl_register_signature {
int index;
struct labcomm_signature *signature;
};
#define LABCOMM_IOCTL_REGISTER_SIGNATURE 0x0001
#define LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN 0x0002
#define LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER 0x0003
#define LABCOMM_IOCTL_WRITER_COPY_BYTES 0x0004
#ifndef _LABCOMM_PRIVATE_H_
#define _LABCOMM_PRIVATE_H_
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <endian.h>
#include <stdio.h>
#endif
#include <stdint.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 0x40
/*
*
*/
#define LABCOMM_DECLARE_SIGNATURE(name) \
struct labcomm_signature name __attribute__((section("labcomm")))
/*
* Semi private decoder declarations
*/
typedef void (*labcomm_handler_function)(void *value, void *context);
typedef void (*labcomm_decoder_function)(
struct labcomm_reader *r,
labcomm_handler_function handler,
void *context);
/*
* Non typesafe registration function to be called from
* generated labcomm_decoder_register_* functions.
*/
void labcomm_internal_decoder_register(
struct labcomm_decoder *d,
struct labcomm_signature *s,
labcomm_decoder_function decoder,
labcomm_handler_function handler,
void *context);
int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
int ioctl_action,
struct labcomm_signature *signature,
va_list args);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(struct labcomm_reader *r) { \
type result; int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (r->pos >= r->count) { \
r->action.fill(r); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
}
#else
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(struct labcomm_reader *r) { \
type result; int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (r->pos >= r->count) { \
r->action.fill(r); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
}
#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 unsigned int labcomm_read_packed32(struct labcomm_reader *r)
{
unsigned int result = 0;
while (1) {
unsigned char tmp;
if (r->pos >= r->count) {
r->action.fill(r);
}
tmp = r->data[r->pos];
r->pos++;
result = (result << 7) | (tmp & 0x7f);
if ((tmp & 0x80) == 0) {
break;
}
}
return result;
}
static inline char *labcomm_read_string(struct labcomm_reader *r)
{
char *result;
int length, i;
length = labcomm_read_packed32(r);
result = malloc(length + 1);
for (i = 0 ; i < length ; i++) {
if (r->pos >= r->count) {
r->action.fill(r);
}
result[i] = r->data[r->pos];
r->pos++;
}
result[length] = 0;
return result;
}
/*
* Semi private encoder declarations
*/
typedef int (*labcomm_encoder_function)(
struct labcomm_writer *,
void *value);
void labcomm_internal_encoder_register(
struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
labcomm_encoder_function encode);
int labcomm_internal_encode(
struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
labcomm_encoder_function encode,
void *value);
int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
int ioctl_action,
struct labcomm_signature *signature,
va_list args);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_ENCODE(name, type) \
static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (w->pos >= w->count) { /*buffer is full*/ \
int err; \
err = w->action.flush(w); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
}
#else
#define LABCOMM_ENCODE(name, type) \
static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (w->pos >= w->count) { \
int err; \
err = w->action.flush(w); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
}
#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 int labcomm_write_packed32(struct labcomm_writer *w,
unsigned int data)
{
unsigned char tmp[5];
int i;
for (i = 0 ; i == 0 || data ; i++, data = (data >> 7)) {
tmp[i] = data & 0x7f;
}
for (i = i - 1 ; i >= 0 ; i--) {
if (w->pos >= w->count) {
int err;
err = w->action.flush(w);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[i] | (i?0x80:0x00);
}
return 0;
}
static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
{
int length, i, err;
length = strlen((char*)s);
err = labcomm_write_packed32(w, length);
if (err != 0) { return err; }
for (i = 0 ; i < length ; i++) {
if (w->pos >= w->count) {
int err;
err = w->action.flush(w);
if (err != 0) { return err; }
}
w->data[w->pos] = s[i];
w->pos++;
}
return 0;
}
#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 <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();
}
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "labcomm_private.h"
#include "labcomm_private.h"
#include "test/gen/generated_encoding.h"
#define IOCTL_WRITER_ASSERT_BYTES 4096
#define IOCTL_WRITER_RESET 4097
static unsigned char buffer[128];
struct labcomm_writer *writer;
static int buf_writer_alloc(struct labcomm_writer *w, char *labcomm_version)
{
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 labcomm_writer *w)
{
return 0;
}
static int buf_writer_start(struct labcomm_writer *w,
struct labcomm_encoder *encoder,
int index,
struct labcomm_signature *signature,
void *value)
{
return 0;
}
static int buf_writer_end(struct labcomm_writer *w)
{
return 0;
}
static int buf_writer_flush(struct labcomm_writer *w)
{
fprintf(stderr, "Should not come here %s:%d\n", __FILE__, __LINE__);
exit(1);
return 0;
}
static int buf_writer_ioctl(
struct labcomm_writer *w,
int action,
struct labcomm_signature *signature,
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;
if (w->pos != count) {
fprintf(stderr, "Invalid length encoded %d != %d (%s:%d)\n",
w->pos, count, __FILE__, line);
mismatch = 1;
}
for (mismatch = 0, i = 0 ; i < count ; i++) {
if (expected[i] >= 0 && expected[i] != buffer[i]) {
mismatch = 1;
}
}
if (mismatch) {
fprintf(stderr, "Encoder mismatch (%s:%d)\n",
__FILE__, line);
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(".. ");
} else {
printf("%2.2x ", expected[i] );
}
}
printf("\n");
exit(1);
}
result = 0;
} break;
case IOCTL_WRITER_RESET: {
w->pos = 0;
result = 0;
}
}
return result;
}
const struct labcomm_writer_action buffer_writer = {
.alloc = buf_writer_alloc,
.free = buf_writer_free,
.start = buf_writer_start,
.end = buf_writer_end,
.flush = buf_writer_flush,
.ioctl = buf_writer_ioctl
};
void dump_encoder(struct labcomm_encoder *encoder)
{
int i;
for (i = 0 ; i < writer->pos ; i++) {
printf("%2.2x ", writer->data[i]);
}
printf("\n");
}
#define EXPECT(...) \
{ \
int expected[] = __VA_ARGS__; \
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, \
__LINE__, \
sizeof(expected)/sizeof(expected[0]), \
expected); \
}
int main(void)
{
generated_encoding_V V;
generated_encoding_B B = 1;
struct labcomm_encoder *encoder = labcomm_encoder_new(buffer_writer, buffer,
NULL, NULL);
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_V(encoder);
EXPECT({ 0x02, -1, 0x01, 'V', 0x11, 0x00 });
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_B(encoder);
EXPECT({0x02, -1, 0x01, 'B', 0x21});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_V(encoder, &V);
EXPECT({-1});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_B(encoder, &B);
EXPECT({-1, 1});
return 0;
}
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 {
}