Commit 087bf1ca authored by Sven Robertz's avatar Sven Robertz
Browse files

partially implemented arrays in example signature parser

parent 3229d26e
...@@ -15,6 +15,7 @@ int main(int argc, char *argv[]) { ...@@ -15,6 +15,7 @@ int main(int argc, char *argv[]) {
encoder = labcomm_encoder_new(labcomm_fd_writer, &fd); encoder = labcomm_encoder_new(labcomm_fd_writer, &fd);
labcomm_encoder_register_simple_TwoInts(encoder); labcomm_encoder_register_simple_TwoInts(encoder);
labcomm_encoder_register_simple_IntString(encoder); labcomm_encoder_register_simple_IntString(encoder);
labcomm_encoder_register_simple_TwoArrays(encoder);
simple_IntString is; simple_IntString is;
is.x = 24; is.x = 24;
is.s = "Hello, LabComm!"; is.s = "Hello, LabComm!";
...@@ -26,4 +27,20 @@ int main(int argc, char *argv[]) { ...@@ -26,4 +27,20 @@ int main(int argc, char *argv[]) {
ti.b = 37; ti.b = 37;
printf("Encoding TwoInts, a=%d, b=%d\n", ti.a, ti.b); printf("Encoding TwoInts, a=%d, b=%d\n", ti.a, ti.b);
labcomm_encode_simple_TwoInts(encoder, &ti); labcomm_encode_simple_TwoInts(encoder, &ti);
int foo[10];
simple_TwoArrays ta;
ta.fixed.a[0] = 17;
ta.fixed.a[1] = 42;
ta.variable.n_0 = 10;
ta.variable.a = foo;
ti.a = 23;
ti.b = 47;
printf("Encoding TwoInts, a=%d, b=%d\n", ti.a, ti.b);
labcomm_encode_simple_TwoInts(encoder, &ti);
labcomm_encode_simple_TwoArrays(encoder, &ta);
} }
...@@ -12,3 +12,8 @@ sample struct { ...@@ -12,3 +12,8 @@ sample struct {
double x; double x;
double y; double y;
} TwoDoubles; } TwoDoubles;
sample struct {
int fixed[2];
int variable[_];
} TwoArrays;
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#define DEBUG
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
...@@ -165,6 +167,26 @@ void dump_signature(unsigned int uid){ ...@@ -165,6 +167,26 @@ void dump_signature(unsigned int uid){
printf("\n"); printf("\n");
} }
int labcomm_sizeof(unsigned int type)
{
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
return 1;
case TYPE_SHORT :
return 2;
case TYPE_INTEGER :
case TYPE_FLOAT :
return 4;
case TYPE_LONG :
case TYPE_DOUBLE :
return 8;
default:
printf("labcomm_sizeof(%x)\n", type);
error("labcomm_sizeof should only be called for primitive types");
}
}
int accept_packet(buffer *d); int accept_packet(buffer *d);
int accept_type_decl(buffer *d); int accept_type_decl(buffer *d);
int accept_sample_decl(buffer *d); int accept_sample_decl(buffer *d);
...@@ -244,11 +266,14 @@ int accept_type_decl(buffer *d){ ...@@ -244,11 +266,14 @@ int accept_type_decl(buffer *d){
accept_user_id(d); accept_user_id(d);
unsigned int uid = pop(d); unsigned int uid = pop(d);
accept_string(d); accept_string(d);
// ignore, for now // ignore, for now. This should do something as
// char *name = (char*) pop(d);
// store or print name
// free(name)
accept_type(d); accept_type(d);
unsigned int type = pop(d); unsigned int type = pop(d);
push(d, type); //push(d, type);
return TRUE; return TRUE;
}else { }else {
return FALSE; return FALSE;
...@@ -266,9 +291,9 @@ int accept_sample_decl(buffer *d){ ...@@ -266,9 +291,9 @@ int accept_sample_decl(buffer *d){
unsigned int start = d->idx; unsigned int start = d->idx;
unsigned int nlen = pop(d); unsigned int nlen = pop(d);
accept_type(d); accept_type(d);
unsigned int dt = pop(d);
unsigned int end = d->idx; unsigned int end = d->idx;
unsigned int len = end-start; unsigned int len = end-start;
printf("signature for uid %x (start=%x,end=%x, nlen=%d,len=%d)\n", uid, start,end, nlen, len);
if(len <= MAX_SIG_LEN) { if(len <= MAX_SIG_LEN) {
signatures_length[uid-USER_ID_BASE] = len; signatures_length[uid-USER_ID_BASE] = len;
memcpy(signatures_name[uid-USER_ID_BASE], &d->c[nstart+3], nlen+1); memcpy(signatures_name[uid-USER_ID_BASE], &d->c[nstart+3], nlen+1);
...@@ -281,6 +306,7 @@ int accept_sample_decl(buffer *d){ ...@@ -281,6 +306,7 @@ int accept_sample_decl(buffer *d){
} else { } else {
error("sig name longer than max length (this ought to be dynamic..."); error("sig name longer than max length (this ought to be dynamic...");
} }
printf("signature for uid %x: %s (start=%x,end=%x, nlen=%d,len=%d)\n", uid, get_signature_name(uid), start,end, nlen, len);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
...@@ -304,8 +330,12 @@ int accept_string(buffer *d){ ...@@ -304,8 +330,12 @@ int accept_string(buffer *d){
push(d, len); push(d, len);
char *str=malloc(len); char *str=malloc(len);
getStr(d, str, len); getStr(d, str, len);
//printf("%s\n", str); printf("%s\n", str);
#ifdef RETURN_STRINGS
push(d, str);
#else
free(str); free(str);
#endif
return TRUE; return TRUE;
} }
// included above // included above
...@@ -390,15 +420,18 @@ int accept_array_decl(buffer *d){ ...@@ -390,15 +420,18 @@ int accept_array_decl(buffer *d){
for(i=0; i<nidx; i++) { for(i=0; i<nidx; i++) {
unsigned int idx = get32(d); unsigned int idx = get32(d);
if(idx == 0) { if(idx == 0) {
printf("variable index,");
numVar++; numVar++;
printf("variable index (numVar=%d), ",numVar);
} else { } else {
printf("fixed index: %d,", idx); printf("fixed index: %d, ", idx);
size*=idx; size*=idx;
} }
printf("\n"); printf("\n");
} }
accept_type(d); unsigned int et=accept_type(d);
printf("array element type: %x\n", et);
pop(d);
//push(d,tid);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
...@@ -426,6 +459,7 @@ int accept_struct_decl(buffer *d){ ...@@ -426,6 +459,7 @@ int accept_struct_decl(buffer *d){
for(i=0; i<nf; i++) { for(i=0; i<nf; i++) {
accept_field(d); accept_field(d);
} }
push(d,tid);
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
...@@ -458,6 +492,50 @@ int accept_sample_data(buffer *d){ ...@@ -458,6 +492,50 @@ int accept_sample_data(buffer *d){
int skip_type(unsigned int,buffer*,unsigned char*,unsigned int,unsigned int*) ; int skip_type(unsigned int,buffer*,unsigned char*,unsigned int,unsigned int*) ;
int skip_array(buffer *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
unsigned int skip = 0;
unsigned int tot_nbr_elem_tmp = 1;
unsigned int nIdx = unpack32(sig, *pos);
printf("skip_array: nIdx = %d\n", nIdx);
*pos +=4;
unsigned int idx[nIdx];
unsigned int nVar=0;
unsigned int i;
for(i=0; i<nIdx; i++) {
idx[i] = unpack32(sig, *pos);
*pos += 4;
printf("skip_array: idx[%d]=%d\n", i, idx[i]);
if(idx[i] == 0) {
nVar++;
} else {
tot_nbr_elem_tmp *= idx[i];
}
}
unsigned int var[nVar];
for(i=0; i<nVar; i++) {
var[i] = get32(d);
printf("skip_array: var[%d]=%d\n", i, var[i]);
}
unsigned int type = unpack32(sig, *pos);
*pos+=4;
unsigned int elemSize = labcomm_sizeof(type);
skip = elemSize * tot_nbr_elem_tmp;
printf("skip_array: skip: %d * %d = %d\n", elemSize, tot_nbr_elem_tmp, skip);
advancen(d, skip);
skip += nVar;
return skip;
}
int skip_struct(buffer *d, unsigned char *sig, unsigned int len, unsigned int *pos) { int skip_struct(buffer *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
unsigned int nFields = unpack32(sig,*pos); unsigned int nFields = unpack32(sig,*pos);
*pos += 4; *pos += 4;
...@@ -527,8 +605,8 @@ int skip_type(unsigned int type, buffer *d, ...@@ -527,8 +605,8 @@ int skip_type(unsigned int type, buffer *d,
skipped+=len+4; skipped+=len+4;
break;} break;}
case ARRAY_DECL : case ARRAY_DECL :
printf("array not implemented\n"); printf("array\n");
exit(1); skipped += skip_array(d, sig, len, pos);
case STRUCT_DECL : case STRUCT_DECL :
printf("struct\n"); printf("struct\n");
skipped += skip_struct(d, sig, len, pos); skipped += skip_struct(d, sig, len, pos);
...@@ -571,8 +649,8 @@ int skip_type(unsigned int type, buffer *d, ...@@ -571,8 +649,8 @@ int skip_type(unsigned int type, buffer *d,
skipped+=len+4; skipped+=len+4;
break;} break;}
case ARRAY_DECL : case ARRAY_DECL :
printf("array not implemented\n"); printf("array\n");
exit(1); skipped += skip_array(d, sig, len, pos);
case STRUCT_DECL : case STRUCT_DECL :
skipped += skip_struct(d, sig, len, pos); skipped += skip_struct(d, sig, len, pos);
break; break;
......
/* labcomm_parser.c:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* functionality into the lib to allow a channel to survive types with no
* registered handler.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEBUG
#define FALSE 0
#define TRUE 1
#define USER_ID_BASE 0x00000080
typedef enum{
TYPE_DECL = 0x00000001,
SAMPLE_DECL = 0x00000002,
ARRAY_DECL = 0x00000010,
STRUCT_DECL = 0x00000011,
TYPE_BOOLEAN = 0x00000020,
TYPE_BYTE = 0x00000021,
TYPE_SHORT = 0x00000022,
TYPE_INTEGER = 0x00000023,
TYPE_LONG = 0x00000024,
TYPE_FLOAT = 0x00000025,
TYPE_DOUBLE = 0x00000026,
TYPE_STRING = 0x00000027
} labcomm_type ;
void error(char *s) {
fprintf(stderr, "%s", s);
fprintf(stderr, "\nexiting\n");
exit(1);
}
#define BUF_SIZE 1024
#define STACK_SIZE 16
/* internal type: stack for the parser */
typedef struct {
unsigned char* c;
unsigned int size;
unsigned int capacity;
unsigned int idx;
unsigned int* stack;
unsigned int top;
} buffer;
/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
static int unpack32(unsigned char *c, unsigned int idx) {
unsigned int b0=(c[idx]) << 3 ;
unsigned int b1=(c[idx+1]) << 2 ;
unsigned int b2=(c[idx+2]) << 1 ;
unsigned int b3=c[idx+3];
return b0 | b1 | b2 | b3;
}
void dumpStack(buffer *b) {
#ifdef DEBUG_STACK
int i;
printf("=== stack: ");
for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
printf("%2.2x ", b->stack[i]);
}
printf(" top==%d\n", b->top);
#endif
}
void push(buffer *b, unsigned int e) {
b->stack[b->top]=e;
b->top=b->top-1;
dumpStack(b);
}
unsigned int pop(buffer *b) {
b->top=b->top+1;
return b->stack[b->top];
}
int init_buffer(buffer *b, size_t size, size_t stacksize) {
b->c = malloc(size);
b->capacity = size;
b->idx = 0;
b->stack = calloc(stacksize, sizeof(b->stack));
b->top = stacksize-1;
return b->c == NULL || b->stack == NULL;
}
int more(buffer *b)
{
return b->idx < b->size;
}
unsigned char get(buffer *b) {
return b->c[b->idx++];
}
unsigned char peek(buffer *b) {
return b->c[b->idx];
}
void advance(buffer *b) {
b->idx++;
}
void advancen(buffer *b, size_t n) {
b->idx+=n;
}
unsigned int peek32(buffer *b) {
return unpack32(b->c, b->idx);
}
void advance32(buffer *b) {
b->idx+=4;
}
unsigned int get32(buffer *b) {
unsigned int res = peek32(b);
advance32(b);
return res;
}
void getStr(buffer *b, char *dest, size_t size) {
int rem = b->size - b->idx;
if( size > rem )
size = rem;
strncpy(dest, &b->c[b->idx], size);
b->idx += size;
}
//XXX experimental
#define MAX_SIGNATURES 10
#define MAX_NAME_LEN 32
#define MAX_SIG_LEN 128
unsigned int signatures_length[MAX_SIGNATURES];
unsigned char signatures_name[MAX_SIGNATURES][MAX_NAME_LEN]; //HERE BE DRAGONS: add range checks
unsigned char signatures[MAX_SIGNATURES][MAX_SIG_LEN];
unsigned int get_signature_len(unsigned int uid){
return signatures_length[uid-USER_ID_BASE];
}
unsigned char* get_signature_name(unsigned int uid){
return &signatures_name[uid-USER_ID_BASE][1];
}
unsigned char* get_signature(unsigned int uid){
return signatures[uid-USER_ID_BASE];
}
void dump_signature(unsigned int uid){
int i;
unsigned int len = get_signature_len(uid);
printf("signature for uid %x : %s (len=%d):\n", uid, get_signature_name(uid), len);
unsigned char* sig = get_signature(uid);
for(i=0; i<len; i++) {
printf("%2.2x ",sig[i]);
if( (i+1)%8==0 ) printf("\n");
}
printf("\n");
}
int labcomm_sizeof(unsigned int type)
{
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
return 1;
case TYPE_SHORT :
return 2;
case TYPE_INTEGER :
case TYPE_FLOAT :
return 4;
case TYPE_LONG :
case TYPE_DOUBLE :
return 8;
default:
printf("labcomm_sizeof(%x)\n", type);
error("labcomm_sizeof should only be called for primitive types");
}
}
int accept_packet(buffer *d);
int accept_type_decl(buffer *d);
int accept_sample_decl(buffer *d);
int accept_user_id(buffer *d);
int accept_string(buffer *d);
int accept_string_length(buffer *d);
int accept_char(buffer *d);
int accept_type(buffer *d);
int accept_boolean_type(buffer *d);
int accept_byte_type(buffer *d);
int accept_short_type(buffer *d);
int accept_integer_type(buffer *d);
int accept_long_type(buffer *d);
int accept_float_type(buffer *d);
int accept_long_type(buffer *d);
int accept_string_type(buffer *d);
int accept_array_decl(buffer *d);
int accept_number_of_indices(buffer *d);
int accept_indices(buffer *d);
int accept_variable_index(buffer *d);
int accept_fixed_index(buffer *d);
int accept_struct_decl(buffer *d);
int accept_number_of_fields(buffer *d);
int accept_field(buffer *d);
int accept_sample_data(buffer *d);
int accept_packed_sample_data(buffer *d);
int do_parse(buffer *d) {
unsigned int type = peek32(d) ;
if(type == TYPE_DECL ) {
advance32(d);
accept_user_id(d);
unsigned int uid = pop(d);
printf(", name = ");
accept_string(d);
// ignore, for now. This should do something as
// char *name = (char*) pop(d);
// store or print name
// free(name)
printf(" : ");
accept_type(d);
unsigned int type = pop(d);
//push(d, type);
printf("\n");
return TRUE;
} else if (type == SAMPLE_DECL) {
advance32(d);
printf("sample ");
accept_user_id(d);
unsigned int nstart = d->idx;
unsigned int uid = pop(d);
printf(", name = ");
accept_string(d);
unsigned int start = d->idx;
unsigned int nlen = pop(d);
accept_type(d);
printf(" : ");
//unsigned int dt = pop(d);
#if 0
unsigned int end = d->idx;
unsigned int len = end-start;
if(len <= MAX_SIG_LEN) {
signatures_length[uid-USER_ID_BASE] = len;
memcpy(signatures_name[uid-USER_ID_BASE], &d->c[nstart+3], nlen+1);
} else {
error("sig longer than max length (this ought to be dynamic...)");
}
if(nlen < MAX_NAME_LEN) { // reserve space for terminating NULL
signatures_name[uid-USER_ID_BASE][nlen+1]=0;
memcpy(signatures[uid-USER_ID_BASE], &d->c[start], len);
} else {
error("sig name longer than max length (this ought to be dynamic...");
}
printf("signature for uid %x: %s (start=%x,end=%x, nlen=%d,len=%d)\n", uid, get_signature_name(uid), start,end, nlen, len);
#endif
} else {
printf("*** got sample data, exiting\n");
exit(0);
}
}
int accept_user_id(buffer *d){
unsigned int uid = peek32(d);
if(uid >= USER_ID_BASE) {
advance32(d);
printf("uid = %x ", uid);
return TRUE;
} else {
return FALSE;
}
}
int accept_string(buffer *d){
unsigned int len = get32(d);
push(d, len);
char *str=malloc(len);
getStr(d, str, len);
printf("%s", str);
#ifdef RETURN_STRINGS
push(d, str);
#else
free(str);
#endif
return TRUE;
}
// included above
// int accept_string_length(buffer *d){
// unsigned int uid = get32(d);
// return TRUE;
//}
//int accept_char(buffer *d){
//}
int accept_type(buffer *d){
unsigned int type = peek32(d);
switch(type) {
case TYPE_BOOLEAN :
printf("boolean");
advance32(d);
break;
case TYPE_BYTE :
printf("byte");
advance32(d);
break;
case TYPE_SHORT :
printf("short");
advance32(d);
break;
case TYPE_INTEGER :
printf("integer");