Commit 274eddf0 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

First stab at propagating writer errors to caller.

parent 45c7b977
......@@ -351,7 +351,7 @@ aspect C_Declarations {
env.println("struct labcomm_encoder *e);");
env.unindent();
env.println("void labcomm_encode_" + env.prefix + getName() + "(");
env.println("int labcomm_encode_" + env.prefix + getName() + "(");
env.indent();
env.println("struct labcomm_encoder *e,");
env.println(env.prefix + getName() + " *v");
......@@ -633,7 +633,7 @@ aspect C_Encoder {
public void SampleDecl.C_emitEncoder(C_env env) {
env = env.nestStruct("(*v)");
env.println("static void encode_" + getName() + "(");
env.println("static int encode_" + getName() + "(");
env.indent();
env.println("labcomm_encoder_t *e,");
env.println(env.prefix + getName() + " *v");
......@@ -641,21 +641,23 @@ aspect C_Encoder {
env.println(")");
env.println("{");
env.indent();
env.println("int result;");
getType().C_emitEncoder(env);
env.println("return result;");
env.unindent();
env.println("}");
// Typesafe encode wrapper
env.println("void labcomm_encode_" + env.prefix + getName() + "(");
env.println("int labcomm_encode_" + env.prefix + getName() + "(");
env.println("labcomm_encoder_t *e,");
env.println(env.prefix + getName() + " *v");
env.unindent();
env.println(")");
env.println("{");
env.indent();
env.println("labcomm_internal_encode(e, &labcomm_signature_" +
env.println("return labcomm_internal_encode(e, &labcomm_signature_" +
env.prefix + getName() +
", (labcomm_encode_typecast_t)encode_" + getName() +
", (labcomm_encoder_function)encode_" + getName() +
", v);");
env.unindent();
env.println("}");
......@@ -668,10 +670,13 @@ aspect C_Encoder {
}
public void VoidType.C_emitEncoder(C_env env) {
env.println("result = 0;");
}
public void PrimType.C_emitEncoder(C_env env) {
env.println("labcomm_encode_" + getName() + "(e, " + env.qualid + ");");
env.println("result = labcomm_encode_" + getName() +
"(e, " + env.qualid + ");");
env.println("if (result != 0) { return result; }");
}
public void UserType.C_emitEncoder(C_env env) {
......@@ -748,7 +753,7 @@ aspect C_Encoder {
env.indent();
env.println("e,");
env.println("&labcomm_signature_" + env.prefix + getName() + ",");
env.println("(labcomm_encode_typecast_t)encode_" + getName());
env.println("(labcomm_encoder_function)encode_" + getName());
env.unindent();
env.println(");");
env.unindent();
......
......@@ -42,7 +42,7 @@ typedef struct labcomm_sample_entry {
labcomm_signature_t *signature;
labcomm_decoder_typecast_t decoder;
labcomm_handler_typecast_t handler;
labcomm_encode_typecast_t encode;
labcomm_encoder_function encode;
void *context;
} labcomm_sample_entry_t;
......@@ -224,32 +224,14 @@ static int get_encoder_index(
#endif
}
void labcomm_encoder_start(struct labcomm_encoder *e,
labcomm_signature_t *s)
{
int index = get_encoder_index(e, s);
e->writer.write(&e->writer, labcomm_writer_start, index);
}
void labcomm_encoder_end(struct labcomm_encoder *e,
labcomm_signature_t *s)
{
e->writer.write(&e->writer, labcomm_writer_end);
}
void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s)
{
int index = get_encoder_index(e, s);
labcomm_encode_packed32(e, index);
}
void labcomm_encode_signature(struct labcomm_encoder *e,
labcomm_signature_t *signature)
{
int i;
e->writer.write(&e->writer, labcomm_writer_start_signature);
labcomm_encode_packed32(e, signature->type);
labcomm_encode_type_index(e, signature);
labcomm_encode_packed32(e, get_encoder_index(e, signature));
labcomm_encode_string(e, signature->name);
for (i = 0 ; i < signature->size ; i++) {
if (e->writer.pos >= e->writer.count) {
......@@ -264,7 +246,7 @@ void labcomm_encode_signature(struct labcomm_encoder *e,
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int encoder_add_signature_by_search(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
labcomm_encoder_function encode)
{
int result;
labcomm_encoder_context_t *context = e->context;
......@@ -289,7 +271,7 @@ static int encoder_add_signature_by_search(struct labcomm_encoder *e,
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
static int encoder_add_signature_by_section(struct labcomm_encoder *e,
labcomm_signature_t *s,
labcomm_encode_typecast_t encode)
labcomm_encoder_function encode)
{
int result = -ENOENT;
......@@ -319,7 +301,7 @@ out:
static int encoder_add_signature(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
labcomm_encoder_function encode)
{
int index = -ENOENT;
......@@ -333,7 +315,7 @@ static int encoder_add_signature(struct labcomm_encoder *e,
static void do_encoder_register(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
labcomm_encoder_function encode)
{
if (signature->type == LABCOMM_SAMPLE) {
if (get_encoder_index(e, signature) == 0) {
......@@ -355,6 +337,7 @@ static void do_encoder_register(struct labcomm_encoder *e,
}
}
/*
static labcomm_sample_entry_t *encoder_get_sample_by_signature_address(
labcomm_encoder_t *encoder,
labcomm_signature_t *s)
......@@ -371,32 +354,30 @@ static labcomm_sample_entry_t *encoder_get_sample_by_signature_address(
#endif
return result;
}
*/
static void do_encode(
labcomm_encoder_t *encoder,
static int do_encode(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
labcomm_encoder_function encode,
void *value)
{
labcomm_sample_entry_t *sample;
sample = encoder_get_sample_by_signature_address(encoder, signature);
(void)sample;
labcomm_encoder_start(encoder, signature);
labcomm_encode_type_index(encoder, signature);
encode(encoder, value);
labcomm_encoder_end(encoder, signature);
/*
labcomm_sample_entry_t *sample;
int result;
labcomm_writer_start_t lws;
sample = encoder_get_sample_by_signature_address(encoder, signature);
if (sample && sample->encode) {
sample->encode(encoder, value);
} else {
encoder->on_error(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE, 2, "No registration for %s.\n", signature->name);
}
*/
lws.encoder = e;
lws.index = get_encoder_index(e, signature);
lws.signature = signature;
lws.value = value;
result = e->writer.write(&e->writer, labcomm_writer_start, &lws);
if (result == -EALREADY) { result = 0; goto out; }
if (result != 0) { goto out; }
result = labcomm_encode_packed32(e, lws.index);
if (result != 0) { goto out; }
result = encode(e, value);
out:
e->writer.write(&e->writer, labcomm_writer_end, &lws);
return result;
}
labcomm_encoder_t *labcomm_encoder_new(
......@@ -435,7 +416,7 @@ labcomm_encoder_t *labcomm_encoder_new(
void labcomm_internal_encoder_register(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
labcomm_encoder_function encode)
{
// Will segfault if e == NULL.
if (e->do_register) {
......@@ -445,17 +426,18 @@ void labcomm_internal_encoder_register(
}
}
void labcomm_internal_encode(
int labcomm_internal_encode(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
labcomm_encoder_function encode,
void *value)
{
if (e->do_encode) {
e->do_encode(e, signature, encode, value);
return e->do_encode(e, signature, encode, value);
} else {
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_ENCODE, 0);
}
return 0;
}
void labcomm_encoder_free(labcomm_encoder_t* e)
......
......@@ -11,7 +11,7 @@ struct labcomm_decoder;
/*
* Signature entry
*/
typedef struct labcomm_signature{
typedef struct labcomm_signature {
int type;
char *name;
int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample *
......@@ -115,12 +115,20 @@ void labcomm_decoder_free(
/*
* Encoder
*/
typedef struct {
struct labcomm_encoder *encoder;
int index;
labcomm_signature_t *signature;
void *value;
} labcomm_writer_start_t;
typedef enum {
labcomm_writer_alloc, /* (..., char *labcomm_version)
Allocate all neccessary data */
labcomm_writer_free, /* Free all allocated data */
labcomm_writer_start, /* Start writing an ordinary sample */
labcomm_writer_start, /* (..., labcomm_writer_start_t *s)
-EALREADY skips further encoding
Start writing an ordinary sample */
labcomm_writer_continue, /* Buffer full during ordinary sample */
labcomm_writer_end, /* End writing ordinary sample */
labcomm_writer_start_signature, /* Start writing signature */
......
......@@ -203,7 +203,7 @@ static inline char *labcomm_decode_string(labcomm_decoder_t *d)
/*
* Semi private encoder declarations
*/
typedef void (*labcomm_encode_typecast_t)(
typedef int (*labcomm_encoder_function)(
struct labcomm_encoder *,
void *value);
......@@ -212,10 +212,10 @@ typedef struct labcomm_encoder {
labcomm_writer_t writer;
void (*do_register)(struct labcomm_encoder *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t);
void (*do_encode)(struct labcomm_encoder *encoder,
labcomm_encoder_function encode);
int (*do_encode)(struct labcomm_encoder *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
labcomm_encoder_function encode,
void *value);
labcomm_error_handler_callback on_error;
} labcomm_encoder_t;
......@@ -223,46 +223,52 @@ typedef struct labcomm_encoder {
void labcomm_internal_encoder_register(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode);
labcomm_encoder_function encode);
void labcomm_internal_encode(
int labcomm_internal_encode(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
labcomm_encoder_function encode,
void *value);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_ENCODE(name, type) \
static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \
static inline int labcomm_write_##name(labcomm_writer_t *w, type data) { \
int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (w->pos >= w->count) { /*buffer is full*/ \
w->write(w, labcomm_writer_continue); \
int err; \
err = w->write(w, labcomm_writer_continue); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
} \
static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
labcomm_write_##name(&e->writer, data); \
static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
return labcomm_write_##name(&e->writer, data); \
}
#else
#define LABCOMM_ENCODE(name, type) \
static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \
static inline int labcomm_write_##name(labcomm_writer_t *w, type data) { \
int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (w->pos >= w->count) { \
w->write(w, labcomm_writer_continue); \
int err; \
err = w->write(w, labcomm_writer_continue); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
} \
static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
labcomm_write_##name(&e->writer, data); \
static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \
return labcomm_write_##name(&e->writer, data); \
}
#endif
......@@ -287,7 +293,8 @@ LABCOMM_ENCODE(double, double)
* 0b1110 - 4 bytes (0x00200000 - 0x0fffffff)
* 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused]
*/
static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data)
static inline int labcomm_write_packed32(labcomm_writer_t *w,
unsigned int data)
{
int n;
unsigned char tag;
......@@ -311,68 +318,86 @@ static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data)
n = 5;
tag = 0xf0;
}
if (w->pos + n - 1 >= w->count) {
/* TODO: maybe?
if (w->pos + n - 1 >= w->count) {
w->write(w, labcomm_writer_continue, n);
}
}
*/
switch (n) {
case 5: {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
if (w->pos >= w->count) {
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos++] = tag; tag = 0;
}
case 4: {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[0] | tag; tag = 0;
}
case 3: {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[1] | tag; tag = 0;
}
case 2: {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[2] | tag; tag = 0;
}
case 1: {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[3] | tag;
}
}
return 0;
}
static inline void labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int data)
static inline int labcomm_encode_packed32(labcomm_encoder_t *e,
unsigned int data)
{
labcomm_pack32(&e->writer, data);
return labcomm_write_packed32(&e->writer, data);
}
static inline void labcomm_write_string(labcomm_writer_t *w, char *s)
static inline int labcomm_write_string(labcomm_writer_t *w, char *s)
{
int length, i;
int length, i, err;
length = strlen((char*)s);
labcomm_pack32(w, length);
err = labcomm_write_packed32(w, length);
if (err != 0) { return err; }
for (i = 0 ; i < length ; i++) {
if (w->pos >= w->count) {
w->write(w, labcomm_writer_continue);
int err;
err = w->write(w, labcomm_writer_continue);
if (err != 0) { return err; }
}
w->data[w->pos] = s[i];
w->pos++;
}
return 0;
}
static inline void labcomm_encode_string(labcomm_encoder_t *e,
static inline int labcomm_encode_string(labcomm_encoder_t *e,
char *s)
{
labcomm_write_string(&e->writer, s);
return labcomm_write_string(&e->writer, s);
}
#endif
......@@ -115,6 +115,15 @@ void dump_encoder(labcomm_encoder_t *encoder)
printf("\n");
}
#define EXPECT(...) \
{ \
int expected[] = __VA_ARGS__; \
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, \
__LINE__, \
sizeof(expected)/sizeof(expected[0]), \
expected); \
}
int main(void)
{
generated_encoding_V V;
......@@ -124,39 +133,19 @@ int main(void)
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_V(encoder);
{
int expected[] = { 0x02, -1, 0x01, 'V', 0x11, 0x00 };
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES,
__LINE__,
6, expected);
}
EXPECT({ 0x02, -1, 0x01, 'V', 0x11, 0x00 });
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_B(encoder);
{
int expected[] = { 0x02, -1, 0x01, 'B', 0x21 };
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES,
__LINE__,
5, expected);
}
EXPECT({0x02, -1, 0x01, 'B', 0x21});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_V(encoder, &V);
{
int expected[] = { -1 };
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES,
__LINE__,
1, expected);
}
EXPECT({-1});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_B(encoder, &B);
{
int expected[] = { -1, 1 };
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES,
__LINE__,
2, expected);
}
EXPECT({-1, 1});
return 0;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment