Commit 1112f3ba authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Changed interface for readers/writers to simplify stacked operation.

Start of adding GPLv3 licensensing.
parent 8c433de9
/*
decimating.c -- LabComm example of a twoway stacked decimation
reader/writer.
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -11,14 +33,8 @@ struct decimating_private {
int encoder_initialized;
struct labcomm_decoder *decoder;
int decoder_initialized;
struct orig_reader {
void *context;
const struct labcomm_reader_action *action;
} orig_reader;
struct orig_writer {
void *context;
const struct labcomm_writer_action *action;
} orig_writer;
struct labcomm_reader_action_context reader_action_context;
struct labcomm_writer_action_context writer_action_context;
LABCOMM_SIGNATURE_ARRAY_DEF(decimation,
struct decimation {
int n;
......@@ -40,67 +56,42 @@ static void set_decimation(
decimation->current = 0;
}
static int wrap_reader_alloc(struct labcomm_reader *r, void *context,
struct labcomm_decoder *decoder,
char *labcomm_version)
static int wrap_reader_alloc(
struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
struct labcomm_decoder *decoder,
char *labcomm_version)
{
int result;
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
struct decimating_private *decimating = action_context->context;
/* Stash away decoder for later use */
decimating->decoder = decoder;
result = orig_reader->action->alloc(r, orig_reader->context,
decoder, labcomm_version);
return result;
return labcomm_reader_alloc(r, action_context->next,
decoder, labcomm_version);
}
static int wrap_reader_free(struct labcomm_reader *r, void *context)
static int wrap_reader_start(
struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
return orig_reader->action->free(r, orig_reader->context);
}
static int wrap_reader_start(struct labcomm_reader *r, void *context)
{
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
struct decimating_private *decimating = action_context->context;
if (! decimating->decoder_initialized) {
decimating->decoder_initialized = 1;
labcomm_decoder_register_decimating_messages_set_decimation(
decimating->decoder, set_decimation, decimating);
}
return orig_reader->action->start(r, orig_reader->context);
}
static int wrap_reader_end(struct labcomm_reader *r, void *context)
{
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
return orig_reader->action->end(r, orig_reader->context);
return labcomm_reader_start(r, action_context->next);
}
static int wrap_reader_fill(struct labcomm_reader *r, void *context)
static int wrap_reader_ioctl(
struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
int signature_index,
struct labcomm_signature *signature,
uint32_t action, va_list args)
{
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
int result;
result = orig_reader->action->fill(r, orig_reader->context);
return result;
}
static int wrap_reader_ioctl(struct labcomm_reader *r, void *context,
int signature_index,
struct labcomm_signature *signature,
uint32_t action, va_list args)
{
struct decimating_private *decimating = context;
struct orig_reader *orig_reader = &decimating->orig_reader;
struct decimating_private *decimating = action_context->context;
if (action == SET_DECIMATION) {
decimating_messages_set_decimation decimation;
......@@ -113,48 +104,42 @@ static int wrap_reader_ioctl(struct labcomm_reader *r, void *context,
return labcomm_encode_decimating_messages_set_decimation(
decimating->encoder, &decimation);
} else {
return orig_reader->action->ioctl(r, orig_reader->context,
signature_index, signature, action, args);
return labcomm_reader_ioctl(r, action_context->next,
signature_index, signature, action, args);
}
}
struct labcomm_reader_action decimating_reader_action = {
.alloc = wrap_reader_alloc,
.free = wrap_reader_free,
.free = NULL,
.start = wrap_reader_start,
.end = wrap_reader_end,
.fill = wrap_reader_fill,
.end = NULL,
.fill = NULL,
.ioctl = wrap_reader_ioctl
};
int wrap_writer_alloc(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder, char *labcomm_version)
static int wrap_writer_alloc(
struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context,
struct labcomm_encoder *encoder, char *labcomm_version)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
struct decimating_private *decimating = action_context->context;
/* Stash away encoder for later use */
decimating->encoder = encoder;
return orig_writer->action->alloc(w, orig_writer->context,
encoder, labcomm_version);
}
int wrap_writer_free(struct labcomm_writer *w, void *context)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
return orig_writer->action->free(w, orig_writer->context);
return labcomm_writer_alloc(w, action_context->next,
encoder, labcomm_version);
}
int wrap_writer_start(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
int index, struct labcomm_signature *signature,
void *value)
static int wrap_writer_start(
struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context,
struct labcomm_encoder *encoder,
int index, struct labcomm_signature *signature,
void *value)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
struct decimating_private *decimating = action_context->context;
struct decimation *decimation;
if (! decimating->encoder_initialized) {
......@@ -169,47 +154,18 @@ int wrap_writer_start(struct labcomm_writer *w, void *context,
return -EALREADY;
} else {
decimation->current = 0;
return orig_writer->action->start(w, orig_writer->context,
encoder, index, signature, value);
return labcomm_writer_start(w, action_context->next,
encoder, index, signature, value);
}
}
int wrap_writer_end(struct labcomm_writer *w, void *context)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
return orig_writer->action->end(w, orig_writer->context);
}
int wrap_writer_flush(struct labcomm_writer *w, void *context)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
return orig_writer->action->flush(w, orig_writer->context);
}
int wrap_writer_ioctl(struct labcomm_writer *w, void *context,
int signature_index,
struct labcomm_signature *signature,
uint32_t action, va_list args)
{
struct decimating_private *decimating = context;
struct orig_writer *orig_writer = &decimating->orig_writer;
return orig_writer->action->ioctl(w, orig_writer->context,
signature_index, signature, action, args);
}
struct labcomm_writer_action decimating_writer_action = {
.alloc = wrap_writer_alloc,
.free = wrap_writer_free,
.free = NULL,
.start = wrap_writer_start,
.end = wrap_writer_end,
.flush = wrap_writer_flush,
.ioctl = wrap_writer_ioctl
.end = NULL,
.flush = NULL,
.ioctl = NULL
};
extern struct decimating *decimating_new(
......@@ -225,15 +181,15 @@ extern struct decimating *decimating_new(
}
/* Wrap reader and writer */
result->orig_reader.context = reader->context;
result->orig_reader.action = reader->action;
reader->context = result;
reader->action = &decimating_reader_action;
result->orig_writer.context = writer->context;
result->orig_writer.action = writer->action;
writer->context = result;
writer->action = &decimating_writer_action;
result->reader_action_context.next = reader->action_context;
result->reader_action_context.action = &decimating_reader_action;
result->reader_action_context.context = result;
reader->action_context = &result->reader_action_context;
result->writer_action_context.next = writer->action_context;
result->writer_action_context.action = &decimating_writer_action;
result->writer_action_context.context = result;
writer->action_context = &result->writer_action_context;
/* Init visible result struct */
result->decimating.reader = reader;
......
......@@ -112,7 +112,9 @@ distclean: clean
# Extra dependencies
$(TEST_DIR)/test_labcomm_basic_type_encoding.o: labcomm_private.h
$(TEST_DIR)/test_labcomm_generated_encoding.o : $(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/test_labcomm_generated_encoding.o: labcomm_private.h
$(TEST_DIR)/test_labcomm_generated_encoding.o: $(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/test_labcomm_generated_encoding : $(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/test_labcomm: $(TEST_GEN_DIR)/test_sample.o
labcomm_fd_reader.o: labcomm_private.h
......
......@@ -4,12 +4,14 @@
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This program is free software: you can redistribute it and/or modify
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.
This program is distributed in the hope that it will be useful,
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.
......@@ -83,6 +85,104 @@ struct labcomm_decoder_context {
struct labcomm_sample_entry *sample;
};
/* Unwrapping reader/writer functions */
#define UNWRAP_ac(func, rw, ac, ...) ac
#define UNWRAP(func, ...) \
while (1) { \
if (UNWRAP_ac(func, __VA_ARGS__)->action->func) { \
return UNWRAP_ac(func, __VA_ARGS__)->action->func(__VA_ARGS__); } \
if (UNWRAP_ac(func, __VA_ARGS__)->next == NULL) { return -ENOSYS; } \
UNWRAP_ac(func, __VA_ARGS__) = UNWRAP_ac(func, __VA_ARGS__)->next; \
}
int labcomm_reader_alloc(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
struct labcomm_decoder *decoder,
char *labcomm_version)
{
UNWRAP(alloc, r, action_context, decoder, labcomm_version);
}
int labcomm_reader_free(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
UNWRAP(free, r, action_context);
}
int labcomm_reader_start(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
UNWRAP(start, r, action_context);
}
int labcomm_reader_end(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
UNWRAP(end, r, action_context);
}
int labcomm_reader_fill(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
UNWRAP(fill, r, action_context);
}
int labcomm_reader_ioctl(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
int index,
struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args)
{
UNWRAP(ioctl, r, action_context, index, signature, ioctl_action, args);
}
int labcomm_writer_alloc(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context,
struct labcomm_encoder *encoder,
char *labcomm_version)
{
UNWRAP(alloc, w, action_context, encoder, labcomm_version);
}
int labcomm_writer_free(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context)
{
UNWRAP(free, w, action_context);
}
int labcomm_writer_start(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context,
struct labcomm_encoder *encoder,
int index, struct labcomm_signature *signature,
void *value)
{
UNWRAP(start, w, action_context, encoder, index, signature, value);
}
int labcomm_writer_end(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context)
{
UNWRAP(end, w, action_context);
}
int labcomm_writer_flush(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context)
{
UNWRAP(flush, w, action_context);
}
int labcomm_writer_ioctl(struct labcomm_writer *w,
struct labcomm_writer_action_context *action_context,
int index,
struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args)
{
UNWRAP(ioctl, w, action_context, index, signature, ioctl_action, args);
}
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback)
{
encoder->on_error = callback;
......@@ -237,20 +337,20 @@ static void labcomm_encode_signature(struct labcomm_encoder *e,
int i, index;
index = get_encoder_index(e, signature);
e->writer->action->start(e->writer, e->writer->context,
e, index, signature, NULL);
labcomm_writer_start(e->writer, e->writer->action_context,
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->context);
labcomm_writer_flush(e->writer, e->writer->action_context);
}
e->writer->data[e->writer->pos] = signature->signature[i];
e->writer->pos++;
}
e->writer->action->end(e->writer, e->writer->context);
labcomm_writer_end(e->writer, e->writer->action_context);
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
......@@ -322,8 +422,8 @@ struct labcomm_encoder *labcomm_encoder_new(
result->lock = lock;
result->on_error = on_error_fprintf;
LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
result->writer->action->alloc(result->writer,result->writer->context,
result, LABCOMM_VERSION);
labcomm_writer_alloc(result->writer,result->writer->action_context,
result, LABCOMM_VERSION);
}
return result;
}
......@@ -364,7 +464,7 @@ int labcomm_internal_encode(
int index;
index = get_encoder_index(e, signature);
result = e->writer->action->start(e->writer, e->writer->context,
result = labcomm_writer_start(e->writer, e->writer->action_context,
e, index, signature, value);
if (result == -EALREADY) { result = 0; goto no_end; }
if (result != 0) { goto out; }
......@@ -372,7 +472,7 @@ int labcomm_internal_encode(
if (result != 0) { goto out; }
result = encode(e->writer, value);
out:
e->writer->action->end(e->writer, e->writer->context);
labcomm_writer_end(e->writer, e->writer->action_context);
no_end:
return result;
}
......@@ -382,7 +482,7 @@ void labcomm_encoder_free(struct labcomm_encoder* e)
struct labcomm_encoder_context *context;
context = (struct labcomm_encoder_context *) e->context;
e->writer->action->free(e->writer, e->writer->context);
labcomm_writer_free(e->writer, e->writer->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(e->registered, int);
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
......@@ -407,44 +507,36 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
int result;
va_list va;
if (encoder->writer->action->ioctl == NULL) {
result = -ENOTSUP;
goto out;
}
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = encoder->writer->action->ioctl(encoder->writer,
encoder->writer->context,
0, NULL, action, va);
result = labcomm_writer_ioctl(encoder->writer,
encoder->writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
static int labcomm_writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
static int writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
{
int result;
va_list va;
if (writer->action->ioctl == NULL) {
result = -ENOTSUP;
goto out;
}
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = writer->action->ioctl(writer, writer->context,
0, NULL, action, va);
result = labcomm_writer_ioctl(writer, writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
......@@ -456,11 +548,9 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
{
int result = -ENOTSUP;
if (encoder->writer->action->ioctl != NULL) {
result = encoder->writer->action->ioctl(encoder->writer,
encoder->writer->context,
-1, signature, action, va);
}
result = labcomm_writer_ioctl(encoder->writer,
encoder->writer->action_context,
-1, signature, action, va);
return result;
}
......@@ -568,13 +658,13 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
int result;
if (d->reader->data == NULL) {
result = d->reader->action->alloc(d->reader, d->reader->context,
d, LABCOMM_VERSION);
result = labcomm_reader_alloc(d->reader, d->reader->action_context,
d, LABCOMM_VERSION);
if (result <= 0) {
goto out;
}
}
result = d->reader->action->start(d->reader, d->reader->context);
result = labcomm_reader_start(d->reader, d->reader->action_context);
if (result > 0) {
struct labcomm_decoder_context *context = d->context;
......@@ -582,36 +672,40 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
/* TODO: should the labcomm_dynamic_buffer_writer be
a permanent part of labcomm_decoder? */
struct labcomm_writer_action_context action_context = {
.next = NULL,
.action = labcomm_dynamic_buffer_writer_action,
.context = NULL
};
struct labcomm_writer writer = {
.context = NULL,
.action_context = &action_context,
.data = NULL,
.data_size = 0,
.count = 0,
.pos = 0,
.error = 0,
.action = labcomm_dynamic_buffer_writer_action,
};
struct labcomm_signature signature;
struct labcomm_sample_entry *entry = NULL;
int index, err;
writer.action->alloc(&writer, writer.context, NULL, "");
writer.action->start(&writer, writer.context, NULL, 0, NULL, NULL);
labcomm_writer_alloc(&writer, writer.action_context, NULL, "");
labcomm_writer_start(&writer, writer.action_context, 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, writer.context);
err = labcomm_writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&signature.size);
labcomm_writer_end(&writer, writer.action_context);
err = 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);
err = 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;
......@@ -639,7 +733,7 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
}
free_signature_name:
free(signature.name);
writer.action->free(&writer, writer.context);
labcomm_writer_free(&writer, writer.action_context);
if (!entry) {
// No handler for found type, bail out (after cleanup)
result = -ENOENT;
......@@ -659,7 +753,7 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)