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 1822 additions and 0 deletions
/*
labcomm2014_renaming_private.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__PRIVATE_H__
#define __LABCOMM2014_RENAMING_PRIVATE_H__
#include "labcomm2014.h"
#include "labcomm2014_renaming.h"
struct labcomm2014_renaming_rename *labcomm2014_renaming_rename_new(
struct labcomm2014_renaming_registry *r,
const struct labcomm2014_signature *signature,
char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
void *context);
void labcomm2014_renaming_rename_free(
struct labcomm2014_renaming_registry *r,
struct labcomm2014_renaming_rename *rename);
const struct labcomm2014_signature *labcomm2014_renaming_rename_signature(
const struct labcomm2014_renaming_rename *rename);
#endif
/*
labcomm2014_renaming_registry.c -- renaming registry
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.h"
#include "labcomm2014_private.h"
#include "labcomm2014_renaming_private.h"
struct alias {
int usecount;
struct alias *next;
char *name;
};
struct registry {
struct registry *base; /* NULL if this is the base type */
const struct labcomm2014_signature *signature;
struct labcomm2014_renaming_rename *rename;
};
struct labcomm2014_renaming_rename {
struct labcomm2014_renaming_rename *next;
int use_count;
struct registry *base;
struct labcomm2014_signature signature;
struct labcomm2014_signature_data s_treedata[2];
};
struct labcomm2014_renaming_registry {
struct labcomm2014_error_handler *error;
struct labcomm2014_memory *memory;
struct labcomm2014_scheduler *scheduler;
LABCOMM_SIGNATURE_ARRAY_DEF(registry, struct registry *);
};
struct labcomm2014_renaming_registry *labcomm2014_renaming_registry_new(
struct labcomm2014_error_handler *error,
struct labcomm2014_memory *memory,
struct labcomm2014_scheduler *scheduler)
{
struct labcomm2014_renaming_registry *result;
result = labcomm2014_memory_alloc(memory, 0, sizeof(*result));
if (! result) {
return NULL;
} else {
result->error = error;
result->memory = memory;
result->scheduler = scheduler;
LABCOMM_SIGNATURE_ARRAY_INIT(result->registry, struct registry *);
return result;
}
}
void labcomm2014_renaming_registry_free(
struct labcomm2014_renaming_registry *r)
{
LABCOMM_SIGNATURE_ARRAY_FREE(r->memory, r->registry, struct registry *);
labcomm2014_memory_free(r->memory, 0, r);
}
static struct registry *registry_new(
struct labcomm2014_renaming_registry *r,
const struct labcomm2014_signature *signature,
struct registry *base)
{
/* Called with registry locked */
struct registry *result = NULL;
struct registry **registry;
int index;
index = labcomm2014_get_local_index(signature);
if (index <= 0) {
labcomm2014_error_warning(r->error,
LABCOMM2014_ERROR_MEMORY,
"Signature has no index: %s\n",
signature->name);
goto out;
}
registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
struct registry *, index);
if (registry == NULL) { goto out; }
if (*registry != NULL) {
result = *registry;
} else {
/* Add previosly unknown sample to registry */
registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
struct registry *, index);
if (registry == NULL) { goto out; }
result = labcomm2014_memory_alloc(r->memory, 0, sizeof(*result));
if (result == NULL) { goto out; }
result->base = base;
result->signature = signature;
result->rename = NULL;
*registry = result;
}
out:
return result;
}
struct labcomm2014_renaming_rename *labcomm2014_renaming_rename_new(
struct labcomm2014_renaming_registry *r,
const struct labcomm2014_signature *signature,
char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
void *context)
{
struct labcomm2014_renaming_rename *result = NULL;
labcomm2014_scheduler_data_lock(r->scheduler);
{
char *new_name = NULL;
static struct registry *base, *renamed;
struct labcomm2014_renaming_rename **l;
base = registry_new(r, signature, NULL);
if (base == NULL) { goto out; }
if (base->base) {
base = base->base;
}
/* Find if renamed entry already exists */
new_name = rename(r->memory, signature->name, context);
if (new_name == NULL) { goto out; }
for (l = &base->rename ; *l ; l = &(*l)->next) {
if (strcmp((*l)->signature.name, new_name) == 0) { break; }
}
if ((*l) == NULL) {
/* Create a new rename entry */
struct labcomm2014_renaming_rename *entry = NULL;
entry = labcomm2014_memory_alloc(r->memory, 0, sizeof(*entry));
if (entry == NULL) { goto out; }
entry->signature.name = new_name;
new_name = NULL;
entry->signature.encoded_size = base->signature->encoded_size;
entry->signature.size = base->signature->size;
entry->signature.signature = base->signature->signature;
entry->signature.index = 0;
#ifndef LABCOMM_NO_TYPEDECL
struct labcomm2014_signature_data s_treedata[2] = {
LABCOMM_SIGDEF_SIGNATURE(*base->signature),
LABCOMM_SIGDEF_END
};
entry->s_treedata[0] = s_treedata[0];
entry->s_treedata[1] = s_treedata[1];
entry->signature.tdsize = sizeof(entry->s_treedata);
entry->signature.treedata = entry->s_treedata;
#endif
labcomm2014_set_local_index(&entry->signature);
renamed = registry_new(r, &entry->signature, base);
if (renamed == NULL) {
/* Failed to create registry entry */
labcomm2014_memory_free(r->memory, 0, entry);
goto out;
} else {
entry->next = NULL;
entry->use_count = 0;
entry->base = base;
(*l) = entry;
}
}
result = *l;
if (result) {
result->use_count++;
}
out:
if (new_name != NULL) {
labcomm2014_memory_free(r->memory, 0, new_name);
}
}
labcomm2014_scheduler_data_unlock(r->scheduler);
return result;
}
void labcomm2014_renaming_rename_free(
struct labcomm2014_renaming_registry *r,
struct labcomm2014_renaming_rename *rename)
{
labcomm2014_scheduler_data_lock(r->scheduler);
rename->use_count--;
if (rename->use_count == 0) {
int index;
struct labcomm2014_renaming_rename **l;
struct registry **registry;
for (l = &rename->base->rename ; *l ; l = &(*l)->next) {
if (*l == rename) { break; }
}
*l = rename->next;
if (rename->base->rename == NULL) {
/* Last use of base signature */
index = labcomm2014_get_local_index(rename->base->signature);
registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
struct registry *, index);
labcomm2014_memory_free(r->memory, 0, *registry);
*registry = NULL;
}
index = labcomm2014_get_local_index(&rename->signature);
registry = LABCOMM_SIGNATURE_ARRAY_REF(r->memory, r->registry,
struct registry *, index);
labcomm2014_memory_free(r->memory, 0, *registry);
*registry = NULL;
/* TODO: We should return the index to the pool*/
labcomm2014_memory_free(r->memory, 0, rename->signature.name);
labcomm2014_memory_free(r->memory, 0, rename);
}
labcomm2014_scheduler_data_unlock(r->scheduler);
}
const struct labcomm2014_signature *labcomm2014_renaming_rename_signature(
const struct labcomm2014_renaming_rename *rename)
{
return &rename->signature;
}
/*
labcomm2014_scheduler.c -- labcomm2014 task coordination
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 "labcomm2014_scheduler_private.h"
#define SCHEDULER_scheduler(scheduler, ...) scheduler
#define SCHEDULER(func, ...) \
if (SCHEDULER_scheduler(__VA_ARGS__) && \
SCHEDULER_scheduler(__VA_ARGS__)->action->func) { \
return SCHEDULER_scheduler(__VA_ARGS__)->action->func(__VA_ARGS__); \
} \
return -ENOSYS;
int labcomm2014_scheduler_free(struct labcomm2014_scheduler *s)
{
SCHEDULER(free, s);
}
int labcomm2014_scheduler_writer_lock(struct labcomm2014_scheduler *s)
{
SCHEDULER(writer_lock, s);
}
int labcomm2014_scheduler_writer_unlock(struct labcomm2014_scheduler *s)
{
SCHEDULER(writer_unlock, s);
}
int labcomm2014_scheduler_data_lock(struct labcomm2014_scheduler *s)
{
SCHEDULER(data_lock, s);
}
int labcomm2014_scheduler_data_unlock(struct labcomm2014_scheduler *s)
{
SCHEDULER(data_unlock, s);
}
struct labcomm2014_time *labcomm2014_scheduler_now(struct labcomm2014_scheduler *s)
{
if (s && s->action->now) {
return s->action->now(s);
}
return NULL;
}
int labcomm2014_scheduler_sleep(struct labcomm2014_scheduler *s,
struct labcomm2014_time *wakeup)
{
SCHEDULER(sleep, s, wakeup);
}
int labcomm2014_scheduler_wakeup(struct labcomm2014_scheduler *s)
{
SCHEDULER(wakeup, s);
}
int labcomm2014_scheduler_enqueue(struct labcomm2014_scheduler *s,
uint32_t delay,
void (*func)(void *context),
void *context)
{
SCHEDULER(enqueue, s, delay, func, context);
}
/*
labcomm2014_scheduler.h -- labcomm2014 task coordination
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/>.
*/
#ifndef __LABCOMM2014_SCHEDULER_H__
#define __LABCOMM2014_SCHEDULER_H__
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <unistd.h>
#include <stdint.h>
#endif
struct labcomm2014_time;
int labcomm2014_time_free(struct labcomm2014_time *t);
int labcomm2014_time_add_usec(struct labcomm2014_time *t, uint32_t usec);
struct labcomm2014_scheduler;
int labcomm2014_scheduler_free(struct labcomm2014_scheduler *s);
/* Lock and event handling */
int labcomm2014_scheduler_writer_lock(struct labcomm2014_scheduler *s);
int labcomm2014_scheduler_writer_unlock(struct labcomm2014_scheduler *s);
int labcomm2014_scheduler_data_lock(struct labcomm2014_scheduler *s);
int labcomm2014_scheduler_data_unlock(struct labcomm2014_scheduler *s);
/* Time handling */
struct labcomm2014_time *labcomm2014_scheduler_now(struct labcomm2014_scheduler *s);
int labcomm2014_scheduler_sleep(struct labcomm2014_scheduler *s,
struct labcomm2014_time *wakeup);
int labcomm2014_scheduler_wakeup(struct labcomm2014_scheduler *s);
/* Deferred action handling */
int labcomm2014_scheduler_enqueue(struct labcomm2014_scheduler *s,
uint32_t delay,
void (*deferred)(void *context),
void *context);
#endif
/*
labcomm2014_scheduler.h -- labcomm2014 task coordination, semi-private part
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/>.
*/
#ifndef __LABCOMM2014_SCHEDULER_PRIVATE_H__
#define __LABCOMM2014_SCHEDULER_PRIVATE_H__
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <unistd.h>
#endif
#include "labcomm2014_scheduler.h"
struct labcomm2014_time {
const struct labcomm2014_time_action {
int (*free)(struct labcomm2014_time *t);
int (*add_usec)(struct labcomm2014_time *t, uint32_t usec);
} *action;
void *context;
};
struct labcomm2014_scheduler {
const struct labcomm2014_scheduler_action {
int (*free)(struct labcomm2014_scheduler *s);
int (*writer_lock)(struct labcomm2014_scheduler *s);
int (*writer_unlock)(struct labcomm2014_scheduler *s);
int (*data_lock)(struct labcomm2014_scheduler *s);
int (*data_unlock)(struct labcomm2014_scheduler *s);
struct labcomm2014_time *(*now)(struct labcomm2014_scheduler *s);
int (*sleep)(struct labcomm2014_scheduler *s,
struct labcomm2014_time *wakeup);
int (*wakeup)(struct labcomm2014_scheduler *s);
int (*enqueue)(struct labcomm2014_scheduler *s,
uint32_t delay,
void (*deferred)(void *context),
void *context);
} *action;
void *context;
};
#endif
/*
labcomm2014_time.c -- labcomm2014 time handling
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 "labcomm2014_scheduler_private.h"
#define TIME_time(time, ...) time
#define TIME(func, ...) \
if (TIME_time(__VA_ARGS__) && \
TIME_time(__VA_ARGS__)->action->func) { \
return TIME_time(__VA_ARGS__)->action->func(__VA_ARGS__); \
} \
return -ENOSYS;
int labcomm2014_time_free(struct labcomm2014_time *s)
{
TIME(free, s);
}
int labcomm2014_time_add_usec(struct labcomm2014_time *s, uint32_t usec)
{
TIME(add_usec, s, usec);
}
#include "labcomm2014.h"
#include <string.h> // for memcmp
#include <stdio.h> // for debug printf
/* Dump signature bytes on stdout
*/
void labcomm2014_signature_print(struct labcomm2014_signature_data *signature)
{
struct labcomm2014_signature_data *p = signature ;
while (p->length != -1) {
if (p->length) {
int i;
for ( i = 0 ; i < p->length ; i++) {
printf("%02x ", p->u.bytes[i]);
}
} else if(p->u.signature){
labcomm2014_signature_print(p->u.signature->treedata);
} else {
printf("neither data nor ref, bailing out.\n");
return;
}
p+=1;
}
printf("\n");
}
static labcomm2014_bool sig_dump_checked(struct labcomm2014_signature_data *signature,
char *buf, int *len, int buflen);
/* buf (out) : byte array to write signature into
len (in/out): input: buf size, out: signature length
return LABCOMM2014_TRUE if aborted due to overrun
*/
labcomm2014_bool labcomm2014_signature_dump(struct labcomm2014_signature_data *signature,
char *buf, int *len)
{
int buflen = *len;
*len = 0;
return sig_dump_checked(signature, buf, len, buflen);
}
/* internal function with bounds checking for buf.
* buflen: capacity of buf
*/
static labcomm2014_bool sig_dump_checked(struct labcomm2014_signature_data *signature,
char *buf, int *len, int buflen)
{
struct labcomm2014_signature_data *p = signature;
while ( (p->length != -1) && (*len < buflen)) {
if (p->length) {
int i;
for ( i = 0 ; (i < p->length) && (*len < buflen); i++) {
*buf++ = p->u.bytes[i];
++*len;
}
} else if(p->u.signature){
int tmplen=*len;
//recursing. c.f. dump()
sig_dump_checked(p->u.signature->treedata, buf, len, buflen);
int inner_len = *len-tmplen;
buf += inner_len;
} else {
//printf("neither data nor ref, bailing out.\n");
return LABCOMM2014_TRUE;
}
p+=1;
}
return (*len >= buflen);
}
/* compare signature (flattened, if needed) to other
return LABCOMM2014_TRUE if equal
*/
labcomm2014_bool labcomm2014_signature_cmp( struct labcomm2014_signature_data *s1,
struct labcomm2014_signature_data *s2)
{
int buflen=512;
char buf1[buflen];
int len1=buflen;
char buf2[buflen];
int len2=buflen;
labcomm2014_bool res1 = labcomm2014_signature_dump(s1, buf1, &len1);
labcomm2014_bool res2 = labcomm2014_signature_dump(s2, buf2, &len2);
if(res1 || res2) {
printf("WARNING: OVERRUN\n");
return LABCOMM2014_FALSE;
} else {
return(len1 == len2 && memcmp(buf1, buf2, len1)==0);
}
}
/* maps a function f(char b, struct labcomm2014_signature *s, void *context)
* on each byte (or type ref) in the signature.
*
* If flatten, the signature is flattened to a byte array, and the
* second argument to f is always zero.
*
* Otherwise, when a type ref is encountered, f is called with the first
* argument zero and the referenced type as the second argument.
*
* The context parameter is passed on, unaltered, to f
*/
void map_signature( void(*f)(char, const struct labcomm2014_signature *, void *),
void *context,
const struct labcomm2014_signature *signature, labcomm2014_bool flatten)
{
struct labcomm2014_signature_data* p = signature->treedata;
while (p->length != -1) {
//fprintf(stderr, "%p %x\n", p, p->length);
if (p->length) {
int i;
for ( i = 0 ; i < p->length ; i++) {
(*f)(p->u.bytes[i], 0, context);
}
} else if (p->u.signature) {
if(p->u.signature == 0) printf("p->u.signature == null\n");
if(flatten) {
map_signature(f, context, p->u.signature, flatten);
} else {
(*f)(0, p->u.signature, context);
}
} else {
fprintf(stderr, "neither data nor ref, bailing out.\n");
return;
}
p+=1;
}
}
#ifndef __LABCOMM2014_TYPE_SIGNATURE_H__
#define __LABCOMM2014_TYPE_SIGNATURE_H__
//XXX move to common.h
#ifndef labcomm2014_bool
#define labcomm2014_bool char
#define LABCOMM2014_TRUE 1
#define LABCOMM2014_FALSE 0
#endif
/*
* Signature entry
*/
#ifndef LABCOMM_NO_TYPEDECL
#ifdef USE_UNIONS
/* Useful for C99 and up (or GCC without -pedantic) */
#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \
union { \
char *bytes; \
struct labcomm2014_signature* signature; \
} u;
#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b }
#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[]
#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 }
#else
#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \
struct { \
char *bytes; \
const struct labcomm2014_signature *signature; \
} u;
#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } }
#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } }
#define LABCOMM_SIGDEF_END { -1, { 0, 0 } }
#endif
struct labcomm2014_signature_data {
int length;
LABCOMM_SIGDEF_BYTES_OR_SIGNATURE
};
#endif
struct labcomm2014_sample_ref;
struct labcomm2014_signature {
char *name;
int (*encoded_size)(const struct labcomm2014_signature *sig, void *); /* void* refers to sample_data */
int size;
unsigned char *signature;
int index;
#ifndef LABCOMM_NO_TYPEDECL
int tdsize;
struct labcomm2014_signature_data *treedata;
#endif
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
int cached_encoded_size; // -1 if not initialized or type is variable size
#endif
};
/* a struct for "raw" type_defs, to be used as an intermediate representation
* between decoder and signature parser
*/
struct labcomm2014_raw_type_def {
char *name;
int index;
int length;
char *signature_data;
};
/* a struct for type bindings
*/
struct labcomm2014_type_binding {
int sample_index;
int type_index;
};
/*
* functions
*/
/* register a handler for type_defs and type bindings
*/
int labcomm2014_decoder_register_labcomm2014_type_def(
struct labcomm2014_decoder *d,
void (*handler)(
struct labcomm2014_raw_type_def *v,
void *context
),
void *context
);
int labcomm2014_decoder_register_labcomm2014_type_binding(
struct labcomm2014_decoder *d,
void (*handler)(
struct labcomm2014_type_binding *v,
void *context
),
void *context
);
/* Dump signature bytes on stdout
*/
void labcomm2014_signature_print(struct labcomm2014_signature_data *signature);
/* compare signatures (flattened, if needed) to other
* return LABCOMM2014_TRUE if equal
*/
labcomm2014_bool labcomm2014_signature_cmp( struct labcomm2014_signature_data *s2,
struct labcomm2014_signature_data *s1);
/* flatten and dump signature to a byte array.
* buf (out) : byte array to write signature into
* len (in/out): input: buf size, out: signature length
*
* return LABCOMM2014_TRUE if aborted due to overrun
*/
labcomm2014_bool labcomm2014_signature_dump(struct labcomm2014_signature_data *signature,
char *buf, int *len);
/* maps function f on each byte in the signature
* if flatten, the signature is flattened, and the second argument of
* f is always zero
* otherwise, when a type ref is encountered, f is called with the first
* argument zero and the type ref as the second argument.
*/
void map_signature( void(*f)(char, const struct labcomm2014_signature *, void *),
void *context,
const struct labcomm2014_signature *signature, labcomm2014_bool flatten);
#endif
gen
sample void V;
sample byte B;
// C Preprocessor macros.
#ifndef CPP_MACROS_H
#define CPP_MACROS_H
#define X_EMPTY(mac) var ## 1
#define EMPTY(mac) X_EMPTY(mac) // Returns 1 if macro mac is empty.
#endif
typedef void unused_t;
typedef void v_t;
sample v_t V;
sample byte B;
sample struct {
int i;
} S1;
sample int I[_];
sample struct { int i; } P[_];
sample void UnusedE;
sample void UnusedD;
sample sample R[4];
#include "labcomm_mem_reader.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
/* This implementation assumes labcomm will call end exactly once after each start
* It is not allowed to save data in mcontext->enc_data,
* this pointer will be set to NULL after decoding.
*/
/* NOTE!!!!
* start will be run first, once a signature or a data section is decoded
* end will be run and then start again. If end of encoded data is reached this
* must be handled in start.
*/
// TODO make labcomm use result!
int labcomm_mem_reader(labcomm_reader_t *r,
labcomm_reader_action_t action,
...)
{
int result = -EINVAL;
labcomm_mem_reader_context_t *mcontext = (labcomm_mem_reader_context_t *) r->context;
switch (action) {
case labcomm_reader_alloc: {
r->data = NULL;
r->data_size = 0;
r->pos = 0;
r->count = 0;
} break;
case labcomm_reader_start: {
if (r->data == NULL && mcontext->enc_data != NULL) {
r->data = (unsigned char *) malloc(mcontext->size);
if(r->data != NULL) {
memcpy(r->data, mcontext->enc_data, mcontext->size);
r->data_size = mcontext->size;
r->count = mcontext->size;
r->pos = 0;
result = r->data_size;
} else {
r->data_size = 0;
result = -ENOMEM;
}
} else if (r->data == NULL && mcontext->enc_data == NULL) {
result = -1;
} else {
result = r->count - r->pos;
}
} break;
case labcomm_reader_continue: {
if (r->pos < r->count) {
result = r->count - r->pos;
} else {
// TODO set some describing error here
result = -1;
}
} break;
case labcomm_reader_end: {
if (r->pos >= r->count) {
free(r->data);
r->data = NULL;
r->data_size = 0;
mcontext->enc_data = NULL;
mcontext->size = 0;
}
result = r->count - r->pos;
} break;
case labcomm_reader_free: {
r->count = 0;
r->pos = 0;
result = 0;
} break;
case labcomm_reader_ioctl: {
result = -ENOTSUP;
}
}
return result;
}
#ifndef LABCOMM_MEM_READER_H
#define LABCOMM_MEM_READER_H
#include "labcomm.h"
/* enc_data: The data to be decoded
* size: the size of the data to be decoded
*/
typedef struct labcomm_mem_reader_context_t labcomm_mem_reader_context_t;
struct labcomm_mem_reader_context_t {
size_t size;
unsigned char *enc_data;
};
int labcomm_mem_reader(labcomm_reader_t *r,
labcomm_reader_action_t action,
...);
#endif
#include "labcomm_mem_writer.h"
#include <stddef.h> // For size_t.
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
#include "labcomm.h"
#include "cppmacros.h"
#define BUFFER_SIZE 150 // Suitable size is at least the size of a fully encoded message. Found by inspecting size of file genreated from the labcomm_fs_reader_writer.c on the same message type.
// Put encdoded data directly in mcontext->mbuf or malloc new temporary memory.
// 1 == Allocate new memory.
// 2 == Use mcontext->buf directly. But _beware_; you can not then later change
// mcontext->buf to something else since the writer gets a reference to this
// buffer!
#if defined(MEM_WRITER_ENCODED_BUFFER) && (EMPTY(MEM_WRITER_ENCODED_BUFFER) != 1)
#define ENCODED_BUFFER MEM_WRITER_ENCODED_BUFFER
#else
#define ENCODED_BUFFER 1
#endif
static int get_writer_available(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext);
static void copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf);
/*
* Write encoded messages to memory. w->context is assumed to be a pointer to a
* labcomm_mem_writer_context_t structure.
*/
int labcomm_mem_writer(labcomm_writer_t *w, labcomm_writer_action_t action, ...)
{
int result = 0;
// Unwrap pointers for easy access.
labcomm_mem_writer_context_t *mcontext = (labcomm_mem_writer_context_t *) w->context;
unsigned char *mbuf = mcontext->buf;
switch (action) {
case labcomm_writer_alloc: {
#if (ENCODED_BUFFER == 1)
w->data = malloc(BUFFER_SIZE); // Buffer that LabComm will use for putting the encoded data.
if (w->data == NULL) {
result = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} else {
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
}
#elif (ENCODED_BUFFER == 2)
w->data = mbuf;
int bytes_left = (mcontext->length - mcontext->write_pos);
w->data_size = bytes_left;
w->count = bytes_left;
w->pos = mcontext->write_pos;
#endif
} break;
case labcomm_writer_free:{
#if (ENCODED_BUFFER == 1)
free(w->data);
#endif
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} break;
case labcomm_writer_start:
case labcomm_writer_start_signature: {
#if (ENCODED_BUFFER == 1)
w->pos = 0;
#elif (ENCODED_BUFFER == 2)
w->pos = mcontext->write_pos;
#endif
} break;
case labcomm_writer_continue:
case labcomm_writer_continue_signature: {
// Encode-buffer(w->data) is full; empty/handle it. (w->pos == w->count) most likely.
#if (ENCODED_BUFFER == 1)
copy_data(w, mcontext, mbuf);
result = w->pos; // Assume result here should be number of bytes written.
w->pos = 0;
#elif (ENCODED_BUFFER == 2)
mcontext->write_pos = w->pos;
#endif
result = 0;
} break;
case labcomm_writer_end:
case labcomm_writer_end_signature:{ // Nothing more to encode, handle encode-buffer(w->data).
#if (ENCODED_BUFFER == 1)
copy_data(w, mcontext, mbuf);
result = w->pos;
w->pos = 0;
#elif (ENCODED_BUFFER == 2)
mcontext->write_pos = w->pos;
#endif
result = 0;
} break;
}
return result;
}
labcomm_mem_writer_context_t *labcomm_mem_writer_context_t_new(size_t init_pos, size_t length, unsigned char *buf)
{
labcomm_mem_writer_context_t *mcontext = (labcomm_mem_writer_context_t *) malloc(sizeof(labcomm_mem_writer_context_t));
if (mcontext == NULL) {
//fprintf(stderr, "error: Can not allocate labcomm_mem_writer_context_t.\n");
} else {
mcontext->write_pos = init_pos;
mcontext->length = length;
mcontext->buf = buf;
}
return mcontext;
}
void labcomm_mem_writer_context_t_free(labcomm_mem_writer_context_t **mcontext)
{
free(*mcontext);
*mcontext = NULL;
}
// Get the number of available bytes in the mcontext->buf buffer.
static int get_writer_available(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext)
{
return (mcontext->length - mcontext->write_pos);
}
// Copy data from encoded buffer to mbuf.
static void copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf)
{
int writer_available = get_writer_available(w, mcontext);
if (( writer_available - w->pos) < 0) {
w->on_error(LABCOMM_ERROR_ENC_BUF_FULL, 3, "labcomm_writer_t->pos=%i, but available in mcontext is %i", w->pos, writer_available);
} else {
int i;
for (i = 0; i < w->pos; ++i, mcontext->write_pos++) {
mbuf[mcontext->write_pos] = w->data[i];
}
}
}
void test_copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf)
{
copy_data(w, mcontext, mbuf);
}
#ifndef LABCOMM_MEM_WRITER_H
#define LABCOMM_MEM_WRITER_H
#include "labcomm.h"
/* Wrapper structure for the memory buffer including a writer position. */
typedef struct labcomm_mem_writer_context_t labcomm_mem_writer_context_t;
struct labcomm_mem_writer_context_t {
size_t write_pos; // Position where next write should be.
size_t length; // Length of the buffer.
unsigned char *buf; // Allocated destination buffer.
};
int labcomm_mem_writer(labcomm_writer_t *w, labcomm_writer_action_t action, ...);
/* Wrapper the internal static function copy_data. This is needed so that the exceptions can be unit tested. */
void test_copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf);
/* Allocate new labcomm_mem_writer_context_t. */
labcomm_mem_writer_context_t *labcomm_mem_writer_context_t_new(size_t init_pos, size_t length, unsigned char *buf);
/* Deallocate mcontext. */
void labcomm_mem_writer_context_t_free(labcomm_mem_writer_context_t **mcontext);
#endif
sample string S;
sample int A[8];
sample struct {
string s1;
string s2;
} NS;
sample string AS[_];
/*
test_labcomm2014.c -- Various labcomm2014 tests
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 <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "labcomm2014_private.h"
#include "labcomm2014_default_error_handler.h"
#include "labcomm2014_default_memory.h"
#include "labcomm2014_default_scheduler.h"
#include "test/gen/test_sample.h"
static struct labcomm2014_writer writer;
static struct expect {
char *description;
int result;
int (*trampoline)(struct labcomm2014_decoder *context);
struct labcomm2014_decoder *context;
} *expect;
static void check_expect()
{
struct expect *p = expect;
{
int i;
for (i = 0 ; i < writer.pos ; i++) {
fprintf(stderr, "%02x ", writer.data[i]);
}
fprintf(stderr, "\n");
}
if (p && p->trampoline) {
int err;
expect = p + 1;
fprintf(stderr, "Checking '%s' expected=%d ", p->description, p->result);
err = p->trampoline(p->context);
fprintf(stderr, "actual=%d\n", err);
if (p->result >= 0 && p->result != err) {
fprintf(stderr, "FAILED\n");
exit(1);
} else if (err == 0) {
fprintf(stderr, "FAILED (unexpected 0)\n");
exit(1);
}
writer.pos = 0;
}
}
static unsigned char buffer[512];
static int writer_alloc(struct labcomm2014_writer *w,
struct labcomm2014_writer_action_context *action_context)
{
w->data = buffer;
w->data_size = sizeof(buffer);
w->count = sizeof(buffer);
return 0;
}
static int 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)
{
check_expect();
return 0;
}
const struct labcomm2014_writer_action writer_action = {
.alloc = writer_alloc,
.start = writer_start,
.end = buf_writer_end,
};
static struct labcomm2014_writer_action_context writer_action_context = {
.next = NULL,
.action = &writer_action,
.context = NULL
};
static struct labcomm2014_writer writer = {
.action_context = &writer_action_context,
.data = buffer,
.data_size = sizeof(buffer),
.count = sizeof(buffer),
.pos = 0,
.error = 0,
};
static int reader_alloc(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
r->data = buffer;
r->data_size = sizeof(buffer);
r->count = 0;
r->memory = labcomm2014_default_memory;
return 0;
}
static int reader_fill(struct labcomm2014_reader *r,
struct labcomm2014_reader_action_context *action_context)
{
r->error = -ENOMEM;
return r->error;
}
const struct labcomm2014_reader_action reader_action = {
.alloc = reader_alloc,
.fill = reader_fill,
};
static struct labcomm2014_reader_action_context reader_action_context = {
.next = NULL,
.action = &reader_action,
.context = NULL
};
static struct labcomm2014_reader reader = {
.action_context = &reader_action_context,
.data = buffer,
.data_size = sizeof(buffer),
.count = 0,
.pos = 0,
.error = 0,
};
static int32_t encoder_data[256];
static test_sample_test_var encoder_var = {
.n_0 = 1,
.n_2 = 1,
.a = encoder_data,
};
static int32_t decoder_data[256];
static test_sample_test_var decoder_var = {
.n_0 = 1,
.n_2 = 1,
.a = decoder_data,
};;
void handle_test_var(test_sample_test_var *v, void *ctx)
{
if (v->n_0 * v->n_2 > 0) {
decoder_var.a[0] = v->a[0];
}
}
int test_decode_one(struct labcomm2014_decoder *decoder)
{
int result;
for (reader.count = 0 ; reader.count < writer.pos ; reader.count++) {
reader.error = 0;
reader.pos = 0;
result = labcomm2014_decoder_decode_one(decoder);
if (result >= 0 ) {
fprintf(stderr,
"Got result from buffer with bogus length (%d, %d != %d)\n",
result, reader.count, writer.pos);
exit(1);
}
}
reader.error = 0;
reader.pos = 0;
reader.count = writer.pos;
result = labcomm2014_decoder_decode_one(decoder);
if (result < 0) {
fprintf(stderr, "Got no result from buffer with correct length (%d)\n",
result);
exit(1);
}
return result;
}
static void test_encode_decode(struct labcomm2014_encoder *encoder,
struct labcomm2014_decoder *decoder,
int expected, uint32_t n_0, uint32_t n_2)
{
int err;
writer.pos = 0;
encoder_var.n_0 = n_0;
encoder_var.n_2 = n_2;
encoder_var.a[0] = 314;
labcomm2014_encode_test_sample_test_var(encoder, &encoder_var);
err = test_decode_one(decoder);
fprintf(stderr, "decode of sample %u * 2 * %u -> size=%d err=%d\n",
n_0, n_2, writer.pos, err);
if (writer.pos != labcomm2014_sizeof_test_sample_test_var(NULL, &encoder_var)) {
fprintf(stderr, "Incorrect sizeof %u * 2 * %u (%d != %d)\n",
n_0, n_2,
writer.pos, labcomm2014_sizeof_test_sample_test_var(NULL, &encoder_var));
exit(1);
}
if (writer.pos != expected) {
fprintf(stderr, "Unexpected size %u * 2 * %u (%d != %d)\n",
n_0, n_2,
writer.pos, expected);
exit(1);
}
}
static int do_test(int argc, char *argv[])
{
int i;
struct labcomm2014_decoder *decoder = labcomm2014_decoder_new(
&reader,
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
struct expect expect_version[] = {
{ "Version", 1, test_decode_one, decoder },
{ 0, 0, 0 }
};
expect = expect_version;
struct labcomm2014_encoder *encoder = labcomm2014_encoder_new(
&writer,
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
labcomm2014_decoder_register_test_sample_test_var(decoder,
handle_test_var,
NULL);
struct expect expect_registration[] = {
{ "Sampledef", -1, test_decode_one, decoder },
#ifdef SHOULD_THIS_BE_REMOVED
{ "Typedef", -1, test_decode_one, decoder },
#endif
{ "Binding", -1, test_decode_one, decoder },
{ 0, 0, 0 }
};
expect = expect_registration;
labcomm2014_encoder_register_test_sample_test_var(encoder);
test_encode_decode(encoder, decoder, 12, 1, 1);
if (decoder_var.a[0] != encoder_var.a[0]) {
fprintf(stderr, "Failed to decode correct value %d != %d\n",
encoder_var.a[0], decoder_var.a[0]);
exit(1);
}
test_encode_decode(encoder, decoder, 36, 2, 2);
test_encode_decode(encoder, decoder, 4, 0, 0);
for (i = 1 ; i <= 4 ; i++) {
test_encode_decode(encoder, decoder, 3+i, 0, (1<<(7*i))-1);
test_encode_decode(encoder, decoder, 4+i, 0, (1<<(7*i)));
}
test_encode_decode(encoder, decoder, 8, 0, 4294967295);
labcomm2014_encoder_free(encoder);
labcomm2014_decoder_free(decoder);
return 0;
}
int main(int argc, char *argv[])
{
return do_test(argc, argv);
}
/*
test_labcomm2014_basic_type_encoding.c -- LabComm tests of basic encoding
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 <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include "labcomm2014_private.h"
static int line;
static unsigned char buffer[128];
static struct labcomm2014_writer writer = {
.action_context = NULL,
.data = buffer,
.data_size = sizeof(buffer),
.count = sizeof(buffer),
.pos = 0,
.error = 0,
};
static struct labcomm2014_reader reader = {
.action_context = NULL,
.data = buffer,
.data_size = sizeof(buffer),
.count = 0,
.pos = 0,
};
typedef uint32_t packed32;
#define TEST_WRITE_READ(type, ltype, format, value, expect_count, expect_bytes) \
{ \
type decoded; \
line = __LINE__; \
writer.pos = 0; \
labcomm2014_write_##ltype(&writer, value); \
writer_assert(#ltype, expect_count, (uint8_t*)expect_bytes); \
reader.count = writer.pos; \
reader.pos = 0; \
decoded = labcomm2014_read_##ltype(&reader); \
if (decoded != value) { \
fprintf(stderr, "Decode error" format " != " format " @%s:%d \n", \
value, decoded, __FILE__, __LINE__); \
exit(1); \
} \
}
static void writer_assert(char *type,
int count,
uint8_t *bytes)
{
if (writer.pos != count) {
fprintf(stderr,
"Wrong number of bytes written for '%s' (%d != %d) @%s:%d\n",
type, writer.pos, count, __FILE__, line);
exit(1);
}
if (memcmp(writer.data, bytes, count) != 0) {
int i;
fprintf(stderr, "Wrong bytes written for '%s' ( ", type);
for (i = 0 ; i < count ; i++) {
fprintf(stderr, "%2.2x ", writer.data[i]);
}
fprintf(stderr, "!= ");
for (i = 0 ; i < count ; i++) {
fprintf(stderr, "%2.2x ", bytes[i]);
}
fprintf(stderr, ") @%s:%d\n", __FILE__, line);
exit(1);
}
}
static int do_test(int argc, char *argv[])
{
TEST_WRITE_READ(packed32, packed32, "%d", 0x0, 1, "\x00");
TEST_WRITE_READ(packed32, packed32, "%d", 0x7f, 1, "\x7f");
TEST_WRITE_READ(packed32, packed32, "%d", 0x80, 2, "\x81\x00");
TEST_WRITE_READ(packed32, packed32, "%d", 0x3fff, 2, "\xff\x7f");
TEST_WRITE_READ(packed32, packed32, "%d", 0x4000, 3, "\x81\x80\x00");
TEST_WRITE_READ(packed32, packed32, "%d", 0x1fffff, 3, "\xff\xff\x7f");
TEST_WRITE_READ(packed32, packed32, "%d", 0x200000, 4, "\x81\x80\x80\x00");
TEST_WRITE_READ(packed32, packed32, "%d", 0xfffffff, 4, "\xff\xff\xff\x7f");
TEST_WRITE_READ(packed32, packed32, "%d", 0x10000000, 5, "\x81\x80\x80\x80\x00");
TEST_WRITE_READ(packed32, packed32, "%d", 0xffffffff, 5, "\x8f\xff\xff\xff\x7f");
TEST_WRITE_READ(uint8_t, boolean, "%d", 0, 1, "\x00");
TEST_WRITE_READ(uint8_t, boolean, "%d", 1, 1, "\x01");
TEST_WRITE_READ(uint8_t, byte, "%d", 0, 1, "\x00");
TEST_WRITE_READ(uint8_t, byte, "%d", 1, 1, "\x01");
TEST_WRITE_READ(uint8_t, byte, "%d", 0xff, 1, "\xff");
TEST_WRITE_READ(int16_t, short, "%d", 0, 2, "\x00\x00");
TEST_WRITE_READ(int16_t, short, "%d", 0x7fff, 2, "\x7f\xff");
TEST_WRITE_READ(int16_t, short, "%d", -1, 2, "\xff\xff");
TEST_WRITE_READ(int32_t, int, "%d", 0, 4, "\x00\x00\x00\x00");
TEST_WRITE_READ(int32_t, int, "%d", 0x7fffffff, 4, "\x7f\xff\xff\xff");
TEST_WRITE_READ(int32_t, int, "%d", -1, 4, "\xff\xff\xff\xff");
TEST_WRITE_READ(int64_t, long, "%" PRId64, INT64_C(0), 8, "\x00\x00\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(int64_t, long, "%" PRId64, INT64_C(0x7fffffffffffffff), 8, "\x7f\xff\xff\xff\xff\xff\xff\xff");
TEST_WRITE_READ(int64_t, long, "%" PRId64, INT64_C(-1), 8, "\xff\xff\xff\xff\xff\xff\xff\xff");
TEST_WRITE_READ(float, float, "%f", 0.0, 4, "\x00\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", 1.0, 4, "\x3f\x80\x00\x00");
TEST_WRITE_READ(float, float, "%f", 2.0, 4, "\x40\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", 0.5, 4, "\x3f\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", 0.25, 4, "\x3e\x80\x00\x00");
TEST_WRITE_READ(float, float, "%f", -0.0, 4, "\x80\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", -1.0, 4, "\xbf\x80\x00\x00");
TEST_WRITE_READ(float, float, "%f", -2.0, 4, "\xc0\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", -0.5, 4, "\xbf\x00\x00\x00");
TEST_WRITE_READ(float, float, "%f", -0.25, 4, "\xbe\x80\x00\x00");
TEST_WRITE_READ(double, double, "%f", 0.0, 8, "\x00\x00\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", 1.0, 8, "\x3f\xf0\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", 2.0, 8, "\x40\x00\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", 0.5, 8, "\x3f\xe0\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", 0.25, 8, "\x3f\xd0\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", -0.0, 8, "\x80\x00\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", -1.0, 8, "\xbf\xf0\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", -2.0, 8, "\xc0\x00\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", -0.5, 8, "\xbf\xe0\x00\x00\x00\x00\x00\x00");
TEST_WRITE_READ(double, double, "%f", -0.25, 8, "\xbf\xd0\x00\x00\x00\x00\x00\x00");
fprintf(stderr, "%s succeded\n", __FILE__);
return 0;
}
int main(int argc, char *argv[])
{
return do_test(argc, argv);
}
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <err.h>
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#include "labcomm2014_default_error_handler.h"
#include "labcomm2014_default_memory.h"
#include "labcomm2014_default_scheduler.h"
#include "labcomm2014_fd_writer.h"
#include "labcomm2014_fd_reader.h"
#include "test/gen/generated_encoding.h"
#include "test/gen/test_sample.h"
#include "test/gen/more_types.h"
#define DATA_FILE "copy_test.dat"
static void handle_s1(generated_encoding_S1 *v, void *context)
{
labcomm2014_copy_generated_encoding_S1(labcomm2014_default_memory, context, v);
}
static void handle_b(generated_encoding_B *v, void *context)
{
labcomm2014_copy_generated_encoding_B(labcomm2014_default_memory, context, v);
}
static void handle_i(generated_encoding_I *v, void *context)
{
labcomm2014_copy_generated_encoding_I(labcomm2014_default_memory, context, v);
}
static void handle_p(generated_encoding_P *v, void *context)
{
labcomm2014_copy_generated_encoding_P(labcomm2014_default_memory, context, v);
}
static void handle_r(generated_encoding_R *v, void *context)
{
labcomm2014_copy_generated_encoding_R(labcomm2014_default_memory, context, v);
}
static void handle_test_var(test_sample_test_var *v, void *context)
{
labcomm2014_copy_test_sample_test_var(labcomm2014_default_memory, context, v);
}
static void handle_a(more_types_A *v, void *context)
{
labcomm2014_copy_more_types_A(labcomm2014_default_memory, context, v);
}
static void handle_s(more_types_S *v, void *context)
{
labcomm2014_copy_more_types_S(labcomm2014_default_memory, context, v);
}
static void handle_ns(more_types_NS *v, void *context)
{
labcomm2014_copy_more_types_NS(labcomm2014_default_memory, context, v);
}
static void handle_as(more_types_AS *v, void *context)
{
labcomm2014_copy_more_types_AS(labcomm2014_default_memory, context, v);
}
int do_test(int argc, char **argv)
{
struct labcomm2014_encoder *encoder;
struct labcomm2014_decoder *decoder;
int fd;
generated_encoding_S1 s1;
generated_encoding_S1 cache_s1;
generated_encoding_B b;
generated_encoding_B cache_b;
generated_encoding_I I;
generated_encoding_I cache_I;
generated_encoding_P p;
generated_encoding_P cache_p;
test_sample_test_var test_var;
test_sample_test_var cache_test_var;
more_types_A a;
more_types_A cache_a;
more_types_S s;
more_types_S cache_s = NULL;
more_types_NS ns;
more_types_NS cache_ns;
more_types_AS as;
more_types_AS cache_as;
generated_encoding_R r;
generated_encoding_R cache_r;
fd = open(DATA_FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
err(1, "open()");
encoder =
labcomm2014_encoder_new(labcomm2014_fd_writer_new(labcomm2014_default_memory, fd, 0),
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
labcomm2014_encoder_register_generated_encoding_S1(encoder);
s1.i = 1;
labcomm2014_encode_generated_encoding_S1(encoder, &s1);
labcomm2014_encoder_register_generated_encoding_B(encoder);
b = 2;
labcomm2014_encode_generated_encoding_B(encoder, &b);
labcomm2014_encoder_register_generated_encoding_I(encoder);
I.n_0 = 3;
I.a = calloc(I.n_0, sizeof(I.a[0]));
I.a[0] = 4;
I.a[1] = 5;
I.a[2] = 6;
labcomm2014_encode_generated_encoding_I(encoder, &I);
labcomm2014_encoder_register_generated_encoding_P(encoder);
p.n_0 = 7;
p.a = calloc(p.n_0, sizeof(p.a[0]));
for (int i = 0; i < p.n_0; i++)
p.a[i].i = 8 + i;
labcomm2014_encode_generated_encoding_P(encoder, &p);
labcomm2014_encoder_register_test_sample_test_var(encoder);
test_var.n_0 = 2;
test_var.n_2 = 7;
test_var.a = calloc(test_var.n_0 * 2 * test_var.n_2, sizeof(*test_var.a));
for (int i = 0; i < test_var.n_0; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < test_var.n_2; k++) {
test_var.a[(((i) * 2 + j) * test_var.n_2) + k] = 100 * i + 10 * j + k;
}
labcomm2014_encode_test_sample_test_var(encoder, &test_var);
labcomm2014_encoder_register_more_types_A(encoder);
for (int i = 0; i < sizeof(a.a) / sizeof(a.a[0]); i++)
a.a[i] = i;
labcomm2014_encode_more_types_A(encoder, &a);
labcomm2014_encoder_register_more_types_S(encoder);
s = "this is a string";
labcomm2014_encode_more_types_S(encoder, &s);
labcomm2014_encoder_register_more_types_NS(encoder);
ns.s1 = "this is a string";
ns.s2 = "this is a another string";
labcomm2014_encode_more_types_NS(encoder, &ns);
labcomm2014_encoder_register_more_types_AS(encoder);
as.n_0 = 3;
as.a = calloc(as.n_0, sizeof(as.a[0]));
as.a[0] = "string 0";
as.a[1] = "string 1";
as.a[2] = "string 2";
labcomm2014_encode_more_types_AS(encoder, &as);
labcomm2014_encoder_register_generated_encoding_R(encoder);
labcomm2014_encoder_sample_ref_register(encoder, labcomm2014_signature_generated_encoding_V);
labcomm2014_encoder_sample_ref_register(encoder,
labcomm2014_signature_generated_encoding_UnusedD);
labcomm2014_encoder_sample_ref_register(encoder, labcomm2014_signature_generated_encoding_R);
r.a[0] = labcomm2014_encoder_get_sample_ref(
encoder, labcomm2014_signature_generated_encoding_V);
r.a[1] = labcomm2014_encoder_get_sample_ref(
encoder, labcomm2014_signature_generated_encoding_UnusedE);
r.a[2] = labcomm2014_encoder_get_sample_ref(
encoder, labcomm2014_signature_generated_encoding_UnusedD);
r.a[3] = labcomm2014_encoder_get_sample_ref(
encoder, labcomm2014_signature_generated_encoding_R);
labcomm2014_encode_generated_encoding_R(encoder, &r);
labcomm2014_encoder_free(encoder);
encoder = NULL;
lseek(fd, 0, SEEK_SET);
decoder =
labcomm2014_decoder_new(labcomm2014_fd_reader_new(labcomm2014_default_memory, fd, 0),
labcomm2014_default_error_handler,
labcomm2014_default_memory,
labcomm2014_default_scheduler);
labcomm2014_decoder_register_generated_encoding_S1(decoder, handle_s1, &cache_s1);
labcomm2014_decoder_register_generated_encoding_B(decoder, handle_b, &cache_b);
labcomm2014_decoder_register_generated_encoding_I(decoder, handle_i, &cache_I);
labcomm2014_decoder_register_generated_encoding_P(decoder, handle_p, &cache_p);
labcomm2014_decoder_register_test_sample_test_var(decoder, handle_test_var,
&cache_test_var);
labcomm2014_decoder_register_more_types_A(decoder, handle_a, &cache_a);
labcomm2014_decoder_register_more_types_S(decoder, handle_s, &cache_s);
labcomm2014_decoder_register_more_types_NS(decoder, handle_ns, &cache_ns);
labcomm2014_decoder_register_more_types_AS(decoder, handle_as, &cache_as);
labcomm2014_decoder_register_generated_encoding_R(decoder, handle_r, &cache_r);
labcomm2014_decoder_sample_ref_register(decoder, labcomm2014_signature_generated_encoding_V);
labcomm2014_decoder_sample_ref_register(decoder,
labcomm2014_signature_generated_encoding_UnusedE);
labcomm2014_decoder_sample_ref_register(decoder, labcomm2014_signature_generated_encoding_R);
while (labcomm2014_decoder_decode_one(decoder) > 0) ;
printf("cache_s1.i = %d, s1.i = %d\n", cache_s1.i, s1.i);
assert(cache_s1.i == s1.i);
puts("S1 copied ok");
assert(cache_b == b);
puts("B copied ok");
assert(cache_I.n_0 == I.n_0);
assert(cache_I.a[0] == I.a[0]);
assert(cache_I.a[1] == I.a[1]);
assert(cache_I.a[2] == I.a[2]);
free(I.a);
puts("I copied ok");
assert(cache_p.n_0 == p.n_0);
for (int i = 0; i < p.n_0; i++)
assert(cache_p.a[i].i == p.a[i].i);
free(p.a);
puts("P copied ok");
assert(cache_test_var.n_0 == test_var.n_0);
assert(cache_test_var.n_2 == test_var.n_2);
for (int i = 0; i < test_var.n_0; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < test_var.n_2; k++) {
assert(cache_test_var.a[(((i) * 2 + j) * test_var.n_2) + k] ==
test_var.a[(((i) * 2 + j) * test_var.n_2) + k]);
assert(cache_test_var.a[(((i) * 2 + j) * test_var.n_2) + k] ==
100 * i + 10 * j + k);
}
free(test_var.a);
puts("test_var copied ok");
for (int i = 0; i < sizeof(a.a) / sizeof(a.a[0]); i++)
assert(cache_a.a[i] == a.a[i]);
puts("A copied ok");
assert(!strcmp(cache_s, s));
puts("S copied ok");
assert(!strcmp(cache_ns.s1, ns.s1));
assert(!strcmp(cache_ns.s2, ns.s2));
puts("NS copied ok");
for (int i = 0; i < as.n_0; i++)
assert(!strcmp(cache_as.a[i], as.a[i]));
free(as.a);
puts("AS copied ok");
fprintf(stderr, "%p %p\n", r.a[0], cache_r.a[0]);
fprintf(stderr, "%p %p\n", r.a[1], cache_r.a[1]);
fprintf(stderr, "%p %p\n", r.a[2], cache_r.a[2]);
fprintf(stderr, "%p %p\n", r.a[3], cache_r.a[3]);
assert(cache_r.a[0] == r.a[0]);
assert(cache_r.a[1] == NULL); /* UnusedE */
assert(cache_r.a[2] == NULL); /* UnusedD */
assert(cache_r.a[3] == r.a[3]);
puts("R copied ok");
labcomm2014_decoder_free(decoder);
close(fd);
unlink(DATA_FILE);
labcomm2014_copy_free_generated_encoding_S1(labcomm2014_default_memory, &cache_s1);
puts("S1 deallocated ok");
labcomm2014_copy_free_generated_encoding_B(labcomm2014_default_memory, &cache_b);
puts("B deallocated ok");
labcomm2014_copy_free_generated_encoding_I(labcomm2014_default_memory, &cache_I);
puts("I deallocated ok");
labcomm2014_copy_free_generated_encoding_P(labcomm2014_default_memory, &cache_p);
puts("P deallocated ok");
labcomm2014_copy_free_test_sample_test_var(labcomm2014_default_memory, &cache_test_var);
puts("test_var deallocated ok");
labcomm2014_copy_free_more_types_A(labcomm2014_default_memory, &cache_a);
puts("A deallocated ok");
labcomm2014_copy_free_more_types_S(labcomm2014_default_memory, &cache_s);
puts("S deallocated ok");
labcomm2014_copy_free_more_types_NS(labcomm2014_default_memory, &cache_ns);
puts("NS deallocated ok");
labcomm2014_copy_free_more_types_AS(labcomm2014_default_memory, &cache_as);
puts("AS deallocated ok");
labcomm2014_copy_free_generated_encoding_R(labcomm2014_default_memory,
&cache_r);
puts("R deallocated ok");
return 0;
}
int main(int argc, char **argv)
{
return do_test(argc, argv);
}