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
Select Git revision
  • anders.blomdell
  • compiler-refactoring
  • java_dyn_msg_dec
  • js
  • labcomm2013
  • labcomm2014
  • labcomm2014_tc31
  • master
  • pragma
  • typeref
  • v2013.0
  • v2014.0
  • v2014.1
13 results

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Select Git revision
  • anders.blomdell
  • compiler-refactoring
  • labcomm2006
  • labcomm2013
  • labcomm2014
  • master
  • pragma
  • python_sig_hash
  • typedefs
  • typeref
  • v2006.0
  • v2013.0
  • v2014.0
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.4
  • v2014.5
  • v2014.6
  • v2015.0
20 results
Show changes
Commits on Source (8)
Discussion 141023
TODO:
*** new labcomm packet types:
TYPE_DEF = 0x03 // for (possibly) hierarchical type definitions
TYPE_BINDING = 0x04 // binding a sample def to a type def
*** rewrite malloc of received samples to utilize the packet length field
to allocate a single object before parsing the sample byte stream
*** labcomm language: add type for type_ref to facilitate references to
labcomm sample_defs (and type_defs) in (primarily) pragmas
E.g., sample ... foo;
sample ... bar;
sample struct {
...
type[2] some_refs;
} some_pragma;
my_lc_some_pragma sp;
sp.some_refs = {&labcomm_signature_my_lc_foo,
&labcomm_signature_my_lc_bar};
labcomm_encode_my_lc_some_pragma(enc, &sp);
This is to avoid exposing local_to_remote and remote_to_local
*** refactor {encoder,decoder}registry to separate the actual encoder
from the registry
- currently, the assignment of local indices is done in the "constructor"
which means that the registries will be very thin
*** labcomm_pragma_builder(struct labcomm_encoder *enc);
- looks like an encoder to enable reuse of the generated encode functions
- allocates memory in the enclosing encoder, enc.
- deallocates memory when packet is sent
*** Pragma handler
- is a decoder, to which the user registers handlers for pragma samples
- has/gets a byte_array_reader in the context
- the "surrounding" decoder will deallocate the pragma packet when the
pragma handler returns
______________________________________________________________
______________preliminary sketch of pragma____________________
A pragma "packet" is a sequence of fields, where each field is
a labcomm sample (in order to keep labcomm in-band self-describing).
A pragma packet has a type, which is a globally unique string
(e.g., java package-like name, URI, or UUID)
One predefined pragma sample type is labcomm_type_ref, which is used to refer
to labcomm sample types in a way that is unique on a given encoder/channel.
Sending:
/* create a pragma packet for pragma type type
allocated in e->memory */
// (or, if that is visible to user code, should
// the parameter be a struct labcomm_memory*?)
struct labcom_pragma_packet * = labcomm_pragma_new(struct labcomm_encoder e*,
char *type);
/* add type reference field*/
void labcomm_pragma_add_ref(struct labcomm_signature sig);
// the semantics if more than one type reference field is undefined
// (as far as labcomm is concerned).
// One possible (pragma-type defined) semantic is that the latest type
// reference applies to the fields following it.
A pragma packet is (under the hood) a struct labcomm_encoder, so that we
can reuse the sample_type_encode() function for adding pragma fields.
// an example session
struct labcom_pragma_packet pp = labcomm_pragma_new(enc, some_type));
labcomm_pragma_add_ref(some_sig);
some_pragma_type_encode(pp, some_pragma_instance);
another_pragma_type_encode(pp, another_pragma_instance);
labcomm_pragma_send(pp, enc);
#define labcomm_pragma_add_field(some_pragma_sample_type, value) \
labcomm_encode_#some_pragma_sample_type, value)
int labcomm_encode_test_twoLines( struct labcomm_encoder *e,
test_twoLines *v)
{
return labcomm_internal_encode(e,
&labcomm_signature_test_twoLines,
(labcomm_enc oder_function) encode_test_twoLines,
v);
}
receiving:
alt 1. standard handlers, parameter pragma_type to handle function
-- this means adding a parameter to all handlers
(where null means not pragma)
void handle_some_pragma(some_pragma *v, void *context, char * pragma_type);
alt 2. standard handlers, but separate register_pragma_handler function
use the handler context to store and communicate pragma-specific data.
-- this means that the decoder interface needs to be extended,
and that the handler context for pragmas need to be specified
(by labcomm)
alt 3 have a single handler for pragma packets as the interface upwards
from the labcomm lib. That handler is then responsible for managing
and multiplexing pragma types based on the type field in the pragma
packet.
The labcomm libraries can provide a default implementation of a
pragma_handler, to facilitate the common cases and reduce the
amount of boilerplate code.
struct pragma_packet {
char *pragma_type;
char *packed_data;
}
void handle_pragma(struct pragma_packet *p, void *context);
......@@ -125,6 +125,21 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
uint32_t ioctl_action,
...);
/* pragma */
struct labcomm_pragma_handler {
//struct labcomm_decoder_registry *registry;
//TODO: implement map (char * pragma_type) --> decoder_registry *
//to allow having different sets of handlers for different pragma types
int foo;
};
typedef int (*labcomm_handle_pragma_callback)(
struct labcomm_decoder *decoder,
char *pragma_type);
void labcomm_decoder_register_pragma_handler(struct labcomm_decoder *d,
labcomm_handle_pragma_callback pragma_dispatcher);
/*
* Encoder
*/
......
/*
labcomm_bytearray_reader.c -- a reader for data in a byte array
Copyright 2014 Sen Gestegård Robertz <sven.robertz@cs.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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm_private.h"
#include "labcomm_bytearray_reader.h"
struct labcomm_bytearray_reader {
struct labcomm_reader reader;
struct labcomm_reader_action_context action_context;
unsigned char *bytearray;
int bytearray_size;
};
static int bytearray_alloc(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
char *version)
{
int result = 0;
r->data = ((struct labcomm_bytearray_reader *)action_context->context)->bytearray;
r->count =((struct labcomm_bytearray_reader *)action_context->context)->bytearray_size;
r->pos = 0;
return result;
}
static int bytearray_free(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
struct labcomm_bytearray_reader *bytearray_reader = action_context->context;
struct labcomm_memory *memory = r->memory;
//HERE BE DRAGONS labcomm_memory_free(memory, 0, r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
labcomm_memory_free(memory, 0, bytearray_reader);
return 0;
}
static int bytearray_fill(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
int result = 0;
if (r->pos < r->count) {
//printf("BAreader.fill: pos %d count: %d\n", r->pos, r->count);
result = r->count - r->pos;
} else {
r->pos = 0;
r->error = -EPIPE;
result = -EPIPE;
}
return result;
}
static const struct labcomm_reader_action action = {
.alloc = bytearray_alloc,
.free = bytearray_free,
.start = NULL,
.fill = bytearray_fill,
.end = NULL,
.ioctl = NULL
};
struct labcomm_reader *labcomm_bytearray_reader_new(struct labcomm_memory *memory,
unsigned char *data, int size)
{
struct labcomm_bytearray_reader *result;
result = labcomm_memory_alloc(memory, 0, sizeof(*result));
if (result == NULL) {
return NULL;
} else {
result->action_context.next = NULL;
result->action_context.action = &action;
result->action_context.context = result;
result->reader.action_context = &result->action_context;
result->reader.memory = memory;
result->bytearray = data;
result->bytearray_size = size;
struct labcomm_reader * res = &result->reader;
// printf("reader: %p, size: %d\n", res, res->data_size);
return res;
}
}
/*
labcomm_bytearray_reader.h -- a reader for data in a byte array
Copyright 2014 Sen Gestegård Robertz <sven.robertz@cs.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 _LABCOMM_BYTEARRAY_READER_H_
#define _LABCOMM_BYTEARRAY_READER_H_
#include "labcomm.h"
struct labcomm_reader *labcomm_bytearray_reader_new(struct labcomm_memory *memory,
unsigned char *data, int size);
#endif
......@@ -25,6 +25,7 @@
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
#include "labcomm_bytearray_reader.h"
struct sample_entry {
int remote_index;
......@@ -75,7 +76,27 @@ struct labcomm_decoder *labcomm_decoder_new(
}
return result;
}
#ifndef WITHOUT_PRAGMA
/* Internal aux function to allow temporary internal decoders
* to share the same memory.
* This function only frees the decoder, not the memory
*/
static void internal_labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
labcomm_reader_free(d->reader, d->reader->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
}
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
internal_labcomm_decoder_free(d);
labcomm_memory_free(memory, 0, d);
}
#else
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
......@@ -85,8 +106,9 @@ void labcomm_decoder_free(struct labcomm_decoder* d)
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
labcomm_memory_free(memory, 0, d);
}
#endif
static int decode_sample(struct labcomm_decoder *d, int kind)
static int decode_sample_def(struct labcomm_decoder *d, int kind)
{
int result;
struct labcomm_signature signature, *local_signature;
......@@ -189,6 +211,74 @@ static void reader_alloc(struct labcomm_decoder *d)
labcomm_reader_alloc(d->reader, d->reader->action_context);
}
}
static int decode_version(struct labcomm_decoder *d, int remote_index)
{
int result;
char *version = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (strcmp(version, CURRENT_VERSION) == 0) {
result = LABCOMM_VERSION;
d->version_ok = 1;
} else {
result = -ECONNRESET;
}
labcomm_memory_free(d->memory, 1, version);
out:
return result;
}
static int decoder_skip(struct labcomm_decoder *d, int len)
{
int i;
for(i = 0; i <len; i++){
labcomm_read_byte(d->reader);
if (d->reader->error < 0) {
return d->reader->error;
}
}
return 0;
}
static int decode_pragma(struct labcomm_decoder *d, int len)
{
char *pragma_type;
int result;
pragma_type = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
int bytes = labcomm_size_string(pragma_type);
int psize = len-bytes;
if(0 /*d->pragma_handler*/) {
//read the entire packet to a buffer and then run
// decode on that through a bytearray_reader.
// (to easily handle multiple labcomm packets in one metadata packet)
int i;
unsigned char pragma_data[psize] ;
for(i=0; i<psize; i++) {
pragma_data[i] = labcomm_read_byte(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
}
struct labcomm_reader *pr = labcomm_bytearray_reader_new(
d->reader->memory, pragma_data, psize);
struct labcomm_decoder *pd = labcomm_decoder_new(
pr, d->error, d->memory, d->scheduler);
/* d->prama_handler(pd, ptype, plen); */
internal_labcomm_decoder_free(pd);
result = 0;
} else {
result = decoder_skip(d, psize);
}
out:
return result;
}
int labcomm_decoder_decode_one(struct labcomm_decoder *d)
{
......@@ -206,25 +296,14 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
goto out;
}
if (remote_index == LABCOMM_VERSION) {
char *version = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (strcmp(version, CURRENT_VERSION) == 0) {
result = LABCOMM_VERSION;
d->version_ok = 1;
} else {
result = -ECONNRESET;
}
labcomm_memory_free(d->memory, 1, version);
result = decode_version(d, remote_index);
} else if (! d->version_ok) {
fprintf(stderr, "No VERSION %d %d\n", remote_index, length);
result = -ECONNRESET;
} else if (remote_index == LABCOMM_SAMPLE) {
result = decode_sample(d, remote_index);
} else if (remote_index == LABCOMM_PRAGMA && 0 /* d->pragma_handler*/) {
/* d->prama_handler(...); */
} else if (remote_index == LABCOMM_SAMPLE_DEF) {
result = decode_sample_def(d, remote_index);
} else if (remote_index == LABCOMM_PRAGMA ){
result = decode_pragma(d, length);
} else if (remote_index < LABCOMM_USER) {
fprintf(stderr, "SKIP %d %d\n", remote_index, length);
result = remote_index;
......
......@@ -25,12 +25,19 @@
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#ifndef WITHOUT_PRAGMA
#include "labcomm_dynamic_buffer_writer.h"
#include "labcomm_bytearray_reader.h"
#endif
struct labcomm_encoder {
struct labcomm_writer *writer;
struct labcomm_error_handler *error;
struct labcomm_memory *memory;
struct labcomm_scheduler *scheduler;
LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
int context_type; //type tag for context. Currently only LABCOMM_PRAGMA
void *context; // for, e.g. parent of pragma packet builder
};
struct labcomm_encoder *labcomm_encoder_new(
......@@ -80,6 +87,134 @@ void labcomm_encoder_free(struct labcomm_encoder* e)
labcomm_memory_free(memory, 0, e);
}
#undef WITHOUT_PRAGMA
#ifndef WITHOUT_PRAGMA
struct pragma_packet_builder {
char * pragma_type;
struct labcomm_encoder* parent;
};
struct labcomm_encoder *labcomm_pragma_builder_new(
struct labcomm_encoder *e,
char * pragma_type) {
struct labcomm_writer *dyn_writer = labcomm_dynamic_buffer_writer_new(
e->memory);
struct labcomm_encoder *pb = labcomm_encoder_new(dyn_writer,
e->error,
e->memory,
e->scheduler);
size_t tlen = 1+strlen(pragma_type);
char* ptype = labcomm_memory_alloc(
e->memory,
1,
tlen);
if(ptype) {
strncpy(ptype, pragma_type, tlen);
} //XXX TODO: and else?
struct pragma_packet_builder* ctxt = labcomm_memory_alloc(
e->memory,
1,
sizeof(struct pragma_packet_builder));
if(ctxt){
ctxt->pragma_type=ptype;
ctxt->parent=e;
}
pb->context_type = LABCOMM_PRAGMA;
pb->context = ctxt;
return pb;
}
//HERE BE DRAGONS! Copied from decoder.c
//Should this be moved to private_h?
static int writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
{
int result;
va_list va;
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = labcomm_writer_ioctl(writer, writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
int labcomm_pragma_send(struct labcomm_encoder* e)
{
//HERE BE DRAGONS!
//We assume that the writer is a dynamic_buffer_writer
if(e->context_type != LABCOMM_PRAGMA) {
printf("context type != PRAGMA, bailing out\n");
return 1;
}
if(!e->context) {
printf("context == NULL, bailing out\n");
return 2;
}
struct pragma_packet_builder* ctx = e->context;
struct labcomm_encoder *p = ctx->parent;
char * pragma_type = ctx->pragma_type;
char* pragma_data;
int err,len;
labcomm_writer_end(e->writer, e->writer->action_context);
err = writer_ioctl(e->writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&len);
if (err < 0) {
// HERE BE DRAGONS!
// What is the difference between error_handler (where is it defined?)
// and error_handler_callback. And why is the latter only in
// the decoder struct?
//
// e->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
// "Failed to get size: %s\n", strerror(-err));
fprintf(stderr, "BAD WRITER, Failed to get size> %s\n", strerror(-err));
err = -ENOENT;
goto free_encoder;
}
err = writer_ioctl(e->writer,
LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
&pragma_data);
if (err < 0) {
// e->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
// "Failed to get pointer: %s\n", strerror(-err));
fprintf(stderr, "BAD WRITER, Failed to get pointer> %s\n", strerror(-err));
err = -ENOENT;
goto free_encoder;
}
{
int data_len = labcomm_size_string(pragma_type) + len;
int i;
labcomm_write_packed32(p->writer, LABCOMM_PRAGMA);
labcomm_write_packed32(p->writer, data_len);
labcomm_write_string(p->writer, pragma_type);
for(i=0; i<len;i++){
labcomm_write_byte(p->writer, pragma_data[i]);
}
labcomm_writer_end(p->writer, p->writer->action_context);
err = p->writer->error;
}
free_encoder:
//XXX are these needed, or is that done in encoder_free?
labcomm_memory_free(e->memory, 1, ctx->pragma_type);
labcomm_memory_free(e->memory, 1, ctx);
labcomm_encoder_free(e);
return err;
}
#endif
int labcomm_internal_encoder_register(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
......@@ -98,7 +233,7 @@ int labcomm_internal_encoder_register(
index, signature, NULL);
if (err == -EALREADY) { result = 0; goto out; }
if (err != 0) { result = err; goto out; }
labcomm_write_packed32(e->writer, LABCOMM_SAMPLE);
labcomm_write_packed32(e->writer, LABCOMM_SAMPLE_DEF);
length = (labcomm_size_packed32(index) +
labcomm_size_string(signature->name) +
labcomm_size_packed32(signature->size) +
......
......@@ -40,7 +40,9 @@
* Allowed packet tags
*/
#define LABCOMM_VERSION 0x01
#define LABCOMM_SAMPLE 0x02
#define LABCOMM_SAMPLE_DEF 0x02
#define LABCOMM_TYPE_DEF 0x03
#define LABCOMM_TYPE_BINDING 0x04
#define LABCOMM_PRAGMA 0x3f
#define LABCOMM_USER 0x40 /* ..0xffffffff */
......
......@@ -11,7 +11,7 @@ public class Constant {
* Predeclared aggregate type indices
*/
public static final int VERSION = 0x01;
public static final int SAMPLE = 0x02;
public static final int SAMPLE_DEF = 0x02;
public static final int PRAGMA = 0x3f;
public static final int FIRST_USER_INDEX = 0x40; /* ..0xffffffff */
......
......@@ -29,7 +29,7 @@ public class DecoderChannel implements Decoder {
version + " != " + Constant.CURRENT_VERSION);
}
} break;
case Constant.SAMPLE: {
case Constant.SAMPLE_DEF: {
int index = decodePacked32();
String name = decodeString();
int signature_length = decodePacked32();
......
......@@ -30,7 +30,7 @@ public class EncoderChannel implements Encoder {
public void register(SampleDispatcher dispatcher) throws IOException {
int index = registry.add(dispatcher);
begin(Constant.SAMPLE);
begin(Constant.SAMPLE_DEF);
encodePacked32(index);
encodeString(dispatcher.getName());
byte[] signature = dispatcher.getSignature();
......
......@@ -11,7 +11,7 @@
# | ...
# +----+--
#
# LabComm220141009 SAMPLE:
# LabComm220141009 SAMPLE_DEF:
#
# +----+----+----+----+
# | id = 0x02 (packed32)
......@@ -50,7 +50,7 @@
# | ...
# +----+--
#
# LabComm2006 SAMPLE:
# LabComm2006 SAMPLE_DEF:
#
# +----+----+----+----+
# | id = 0x00000002 |
......@@ -124,7 +124,7 @@ DEFAULT_VERSION = "LabComm20141009"
# Allowed packet tags
i_VERSION = 0x01
i_SAMPLE = 0x02
i_SAMPLE_DEF = 0x02
i_PRAGMA = 0x3f
i_USER = 0x40 # ..0xffffffff
......@@ -310,7 +310,7 @@ class sample(object):
self.decl = decl
def encode_decl(self, encoder):
encoder.encode_type(i_SAMPLE)
encoder.encode_type(i_SAMPLE_DEF)
with length_encoder(encoder) as e1:
e1.encode_type(encoder.decl_to_index[self])
e1.encode_string(self.name)
......@@ -512,7 +512,7 @@ class struct:
result += "\n])"
return result
SAMPLE = sample(None, None)
SAMPLE_DEF = sample(None, None)
ARRAY = array(None, None)
STRUCT = struct({})
......@@ -541,7 +541,7 @@ class Codec(object):
self.predefined_types()
def predefined_types(self):
self.add_decl(SAMPLE, i_SAMPLE)
self.add_decl(SAMPLE_DEF, i_SAMPLE_DEF)
self.add_decl(ARRAY, i_ARRAY)
self.add_decl(STRUCT, i_STRUCT)
......@@ -705,7 +705,7 @@ class Decoder(Codec):
if self.version != other_version:
raise Exception("LabComm version mismatch %s != %s" %
(version, other_version))
if index == i_SAMPLE:
if index == i_SAMPLE_DEF:
decl = self.index_to_decl[index].decode_decl(self)
value = None
else:
......