Commit 76407049 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Implementation of renaming encoder. Typedef trees are not correctly encoded!

parent 732bf4bf
......@@ -20,9 +20,11 @@ OBJS=labcomm$(VERSION).o \
labcomm$(VERSION)_decoder.o \
labcomm$(VERSION)_dynamic_buffer_writer.o \
labcomm$(VERSION)_fd_reader.o \
labcomm$(VERSION)_type_signature.o \
labcomm$(VERSION)_type_signature.o \
labcomm$(VERSION)_fd_writer.o \
labcomm$(VERSION)_pthread_scheduler.o
labcomm$(VERSION)_pthread_scheduler.o \
labcomm$(VERSION)_renaming.o \
labcomm$(VERSION)_renaming_encoder.o
# Enable experimental objects by `make LABCOMM_EXPERIMENTAL=true`
ifeq ($(LABCOMM_EXPERIMENTAL),true)
......@@ -46,7 +48,8 @@ TESTS=test_labcomm_basic_type_encoding \
test_signature_numbers \
test_labcomm \
test_labcomm_pthread_scheduler \
test_labcomm_copy
test_labcomm_copy \
test_labcomm_renaming
#FIXME: test_labcomm_errors
TEST_DIR=test
......@@ -169,3 +172,6 @@ $(TEST_DIR)/gen/test_labcomm_copy: \
$(TEST_DIR)/gen/generated_encoding.o \
$(TEST_DIR)/gen/test_sample.o \
$(TEST_DIR)/gen/more_types.o
$(TEST_DIR)/gen/test_labcomm_renaming: \
$(TEST_DIR)/gen/generated_encoding.o
/*
labcomm2014_renaming.c -- functions intended for renaming
encoders and decoders
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 "labcomm2014_renaming.h"
#include <string.h>
#include <stdio.h>
char *labcomm2014_renaming_prefix(struct labcomm2014_memory *m,
char *name, void *context)
{
char *result, *prefix = context;
int length;
length = strlen(name) + strlen(prefix) + 1;
result = labcomm2014_memory_alloc(m, 0, length);
if (result != NULL) {
strcpy(result, prefix);
strcat(result, name);
}
fprintf(stderr, "%s + %s -> %s\n", prefix, name, result);
return result;
}
char *labcomm2014_renaming_suffix(struct labcomm2014_memory *m,
char *name, void *context)
{
return labcomm2014_renaming_prefix(m, context, name);
}
/*
labcomm2014_renaming.h -- functions intended for renaming
encoders and decoders
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/>.
*/
#ifndef __LABCOMM2014_RENAMING_H__
#define __LABCOMM2014_RENAMING_H__
#include "labcomm2014.h"
char *labcomm2014_renaming_prefix(struct labcomm2014_memory *m,
char *name, void *context);
char *labcomm2014_renaming_suffix(struct labcomm2014_memory *m,
char *name, void *context);
#endif
/*
labcomm2014_renaming_encoder.c -- a stacked encoder that renames samples
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 <errno.h>
#include "labcomm2014_renaming_encoder.h"
#include "labcomm2014.h"
#include "labcomm2014_private.h"
struct encoder {
struct labcomm2014_encoder encoder;
struct labcomm2014_encoder *next;
char *(*rename)(struct labcomm2014_memory *m, char *name, void *context);
void *context;
LABCOMM_SIGNATURE_ARRAY_DEF(renamed, struct labcomm2014_signature *);
};
static struct labcomm2014_signature *get_renamed(
struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature)
{
struct labcomm2014_signature *result;
struct encoder *ie = e->context;
int index;
index = labcomm2014_get_local_index(signature);
labcomm2014_scheduler_writer_lock(e->scheduler);
result = LABCOMM_SIGNATURE_ARRAY_GET(ie->renamed,
struct labcomm2014_signature *,
index, NULL);
labcomm2014_scheduler_writer_unlock(e->scheduler);
return result;
}
static struct labcomm2014_signature *set_renamed(
struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature)
{
struct labcomm2014_signature *result;
result = get_renamed(e, signature);
if (result == NULL) {
/* create a renamed sample */
struct encoder *ie = e->context;
int index;
struct labcomm2014_signature **renamed;
index = labcomm2014_get_local_index(signature);
if (index <= 0) { goto out; /*result already NULL */}
labcomm2014_scheduler_writer_lock(e->scheduler);
renamed = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, ie->renamed,
struct labcomm2014_signature *,
index);
if (renamed == NULL) {
labcomm2014_error_warning(e->error,
LABCOMM2014_ERROR_MEMORY,
"Could not allocate rename slot: %s\n",
signature->name);
goto unlock;
}
if (*renamed != NULL) {
/* Somebody beat as to allocation, this should never happen */
goto unlock;
}
result = labcomm2014_memory_alloc(e->memory, 0, sizeof(*result));
if (result == NULL) {
labcomm2014_error_warning(e->error,
LABCOMM2014_ERROR_MEMORY,
"Could not allocate rename signature: %s\n",
signature->name);
goto unlock;
}
result->name = ie->rename(e->memory, signature->name, ie->context);
if (result->name == NULL) {
labcomm2014_error_warning(e->error,
LABCOMM2014_ERROR_MEMORY,
"Could not allocate rename name: %s\n",
signature->name);
goto unlock_free_result;
}
result->encoded_size = signature->encoded_size;
result->size = signature->size;
result->signature = signature->signature;
result->index = 0;
#ifndef LABCOMM_NO_TYPEDECL
result->tdsize = signature->tdsize;
result->treedata = signature->treedata;
#endif
labcomm2014_set_local_index(result);
*renamed = result;
goto unlock;
unlock_free_result:
labcomm2014_memory_free(e->memory, 0, result);
result = NULL;
unlock:
labcomm2014_scheduler_writer_unlock(e->scheduler);
out:
;
}
return result;
}
static int do_type_register(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature)
{
struct encoder *ie = e->context;
return ie->next->type_register(ie->next, set_renamed(e, signature));
}
static int do_type_bind(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature,
char has_deps)
{
struct encoder *ie = e->context;
return ie->next->type_bind(ie->next, set_renamed(e, signature), has_deps);
}
static int do_sample_register(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature,
labcomm2014_encoder_function encode)
{
struct encoder *ie = e->context;
return ie->next->sample_register(ie->next, set_renamed(e, signature), encode);
}
static int do_ref_register(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature)
{
struct encoder *ie = e->context;
return ie->next->ref_register(ie->next, set_renamed(e, signature));
}
static int do_encode(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature,
labcomm2014_encoder_function encode,
void *value)
{
struct encoder *ie = e->context;
return ie->next->encode(ie->next, get_renamed(e, signature), encode, value);
}
static int do_ioctl(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature,
uint32_t ioctl_action, va_list args)
{
struct encoder *ie = e->context;
return ie->next->ioctl(ie->next, get_renamed(e, signature),
ioctl_action, args);
}
static int do_signature_to_index(struct labcomm2014_encoder *e,
const struct labcomm2014_signature *signature)
{
struct encoder *ie = e->context;
return ie->next->signature_to_index(ie->next, get_renamed(e, signature));
}
static void do_free(struct labcomm2014_encoder *e)
{
struct encoder *ie = e->context;
int i;
LABCOMM_SIGNATURE_ARRAY_FOREACH(ie->renamed, struct labcomm2014_signature *,
i) {
struct labcomm2014_signature *s;
s = LABCOMM_SIGNATURE_ARRAY_GET(ie->renamed,
struct labcomm2014_signature *, i, NULL);
if (s) {
labcomm2014_memory_free(e->memory, 0, s->name);
labcomm2014_memory_free(e->memory, 0, s);
}
}
LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, ie->renamed,
struct labcomm2014_signature *);
labcomm2014_memory_free(e->memory, 0, ie);
}
struct labcomm2014_encoder *labcomm2014_renaming_encoder_new(
struct labcomm2014_encoder *e,
char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
void *context)
{
struct encoder *result;
result = labcomm2014_memory_alloc(e->memory, 0, sizeof(*result));
if (!result) {
return NULL;
} else {
result->encoder.context = result;
result->encoder.writer = NULL;
result->encoder.error = e->error;
result->encoder.memory = e->memory;
result->encoder.scheduler = e->scheduler;
result->encoder.free = do_free;
result->encoder.type_register = do_type_register;
result->encoder.type_bind = do_type_bind;
result->encoder.sample_register = do_sample_register;
result->encoder.ref_register = do_ref_register;
result->encoder.encode = do_encode;
result->encoder.ioctl = do_ioctl;
result->encoder.signature_to_index = do_signature_to_index;
result->next = e;
result->rename = rename;
result->context = context;
LABCOMM_SIGNATURE_ARRAY_INIT(result->renamed,
struct labcomm2014_signature *);
return &(result->encoder);
}
}
/*
labcomm2014_renaming_encoder.h -- a stacked encoder that renames samples
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/>.
*/
#ifndef __LABCOMM2014_RENAMING_ENCODER_H__
#define __LABCOMM2014_RENAMING_ENCODER_H__
#include "labcomm2014.h"
struct labcomm2014_encoder *labcomm2014_renaming_encoder_new(
struct labcomm2014_encoder *e,
char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
void *context);
#endif
</
/*
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_pthread_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 (%d: != %d)\n",
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++) {
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");
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");
}
int main(void)
{
struct labcomm2014_encoder *encoder, *prefix, *suffix;
int i;
for (i = 0 ; i < sizeof(seen_variable)/sizeof(seen_variable[0]) ; i++) {
seen_variable[i] = -1;
}
encoder = labcomm2014_encoder_new(
&buffer_writer,
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_pthread_scheduler_new(labcomm2014_default_memory));
prefix = labcomm2014_renaming_encoder_new(encoder,
labcomm2014_renaming_prefix,
"p.");
suffix = labcomm2014_renaming_encoder_new(prefix,
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, 0x06, VARIABLE(0), 0x01, 'V', 0x02, 0x11, 0x00,
0x04, 0x08, VARIABLE(1), 0x03, 'v', '_', 't', 0x02, 0x11, 0x00,
0x04, 0x05, VARIABLE(2), 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);