labcomm_sig_parser.c 21.5 KB
Newer Older
Sven Robertz's avatar
Sven Robertz committed
1
/* labcomm_sig_parser.c:
2
3
4
5
6
7
 * 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.
 */

Sven Robertz's avatar
Sven Robertz committed
8
9
10
11
12
13
14
15

/* TODO, and notes about strange quirks
 *
 * - the return values for the accept_ functions are not really used anymore
 *   as the parser "peeks" and calls the correct accept function instead. 
 *   This should be refactored
 *
 * - The RETURN_STRINGS and where/if to allocate strings is to be decided, it
Sven Robertz's avatar
comment    
Sven Robertz committed
16
 *   is currently not used
17
 * 
Sven Robertz's avatar
comment    
Sven Robertz committed
18
19
20
21
22
23
 * - TYPE_DECL is not tested (is it ever sent?)
 * 
 * - The dynamic allocation of the parser is not quite dynamic, the sizes are
 *   set through the init function, and are then static.
 *   This should be adapted when allocation is parameterized/user-definable
 *   for the entire lib.
Sven Robertz's avatar
Sven Robertz committed
24
25
26
27
 */
      


28
29
30
31
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

32
#include "labcomm_sig_parser.h"
Sven Robertz's avatar
Sven Robertz committed
33

34
static void error(char *s) {
35
	fprintf(stderr, "ERROR: %s", s);
36
37
38
39
40
	fprintf(stderr, "\nexiting\n");
	exit(1);
}

/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
Sven Robertz's avatar
Sven Robertz committed
41
42
43
44
45
46
47
48
static unsigned 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;
}
49

50
static inline unsigned int get32(labcomm_sig_parser_t *b) {
Sven Robertz's avatar
Sven Robertz committed
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
       unsigned int res = unpack32(b->c, b->idx);
       b->idx+=4;
       return res;
}


/* aux method for reading labcomm varint from a char* 
   size is an out parameter: if not NULL the number of bytes read will be written here
*/
static int unpack_varint(unsigned char *buf, unsigned int idx, unsigned char *size) {
        unsigned int res = 0;
        unsigned int i=0;
        unsigned char cont = TRUE;

        do {
                unsigned char c = buf[idx+i];
                res |= (c & 0x7f) << 7*i;
                cont = c & 0x80;
                i++;
        } while(cont);

	if(size != NULL)
		*size = i; 
        return res;
75
76
}

77
void dumpValStack(labcomm_sig_parser_t *b) {
78
	int i;
79
	printf("=== value stack: ");
80
#ifdef DEBUG_STACK_VERBOSE
81
	for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
82
		printf("%2.2x ", b->val_stack[i]);
83
	}
84
#endif
85
	printf("    top==%d\n", b->val_top);
86
}
87
void dumpPtrStack(labcomm_sig_parser_t *b) {
88
89
	int i;
	printf("=== pointer stack: ");
90
#ifdef DEBUG_STACK_VERBOSE
91
92
93
	for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
		printf("%2.2x ", b->ptr_stack[i]);
	}
94
#endif
95
	printf("    top==%d\n", b->ptr_top);
96
97
}

98
void push_val(labcomm_sig_parser_t *b, unsigned int e) {
99
100
	b->val_stack[b->val_top]=e;
	b->val_top=b->val_top-1;
101
102
	if(b->val_top<0) error("value stack overrun");
#if defined DEBUG && !defined QUIET_STACK
103
	dumpValStack(b);
Sven Robertz's avatar
Sven Robertz committed
104
#endif
105
}
106
unsigned int pop_val(labcomm_sig_parser_t *b) {
107
	b->val_top=b->val_top+1;
108
109
110
111
	if(b->val_top>b->stacksize) error("value stack underrun");
#if defined DEBUG && !defined QUIET_STACK
	dumpValStack(b);
#endif
112
113
	return b->val_stack[b->val_top];
}
114
void push_ptr(labcomm_sig_parser_t *b, void* e) {
115
116
	b->ptr_stack[b->ptr_top]=e;
	b->ptr_top=b->ptr_top-1;
117
	if(b->ptr_top<0) error("pointer stack overrun");
Sven Robertz's avatar
Sven Robertz committed
118
#ifdef DEBUG
119
	dumpPtrStack(b);
Sven Robertz's avatar
Sven Robertz committed
120
#endif
121
}
122
void* pop_ptr(labcomm_sig_parser_t *b) {
123
	b->ptr_top=b->ptr_top+1;
124
125
126
127
	if(b->ptr_top>b->stacksize) error("pointer stack underrun");
#ifdef DEBUG
	dumpPtrStack(b);
#endif
128
	return b->ptr_stack[b->ptr_top];
129
130
}
	
131
132
133
134
135
136
int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size, 
                            size_t stacksize, size_t num_signatures,
                            size_t max_name_len, size_t max_sig_len) 
{
	b->c = malloc(buffer_size);
	b->capacity = buffer_size;
137
	b->size = 0;
138
139
	b->idx = 0;

140
	b->stacksize = stacksize;
141

142
143
144
145
146
147
	b->val_stack = calloc(stacksize, sizeof(b->val_stack));
	b->val_top = stacksize-1;

	b->ptr_stack = calloc(stacksize, sizeof(b->ptr_stack));
	b->ptr_top = stacksize-1;

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
	b->max_signatures = num_signatures;
	b->max_name_len = max_name_len;
	b->max_sig_len = max_sig_len;

#ifdef STATIC_ALLOCATION
	printf("warning: labcomm_sig_parser_t_init: size params ignored, using defaults from .h file \n");
#else
	b->sig_ts=calloc(num_signatures, sizeof(labcomm_signature_t));
	b->signatures_length=calloc(num_signatures, sizeof(int));
	b->signatures_name_length=calloc(num_signatures, sizeof(int));
	b->signatures_name=calloc(num_signatures, sizeof(void *)); //HERE BE DRAGONS: add range checks
	b->signatures=calloc(num_signatures, sizeof(void *));
	int i;
	for(i = 0; i<num_signatures; i++) {
		b->signatures[i] = calloc(b->max_sig_len, sizeof(char));
		b->signatures_name[i] = calloc(b->max_name_len, sizeof(char));
	}
#endif
166
	return b->c == NULL || b->val_stack == NULL || b->ptr_stack == NULL;
167
168
}

169
int labcomm_sig_parser_read_file(labcomm_sig_parser_t *b, FILE *f) {
170
171
172
173
174
175
        int s = fread(b->c, sizeof(char), b->capacity, f);
        b->size = s;
        b->idx=0;
        return s;
}

176
int more(labcomm_sig_parser_t *b) 
177
178
179
180
{
	return b->idx < b->size;
}

181
unsigned char get(labcomm_sig_parser_t *b) {
182
183
184
	return b->c[b->idx++];
}

185
unsigned char peek(labcomm_sig_parser_t *b) {
186
187
188
	return b->c[b->idx];
}

189
void advance(labcomm_sig_parser_t *b) {
190
191
192
	b->idx++;
}

193
void advancen(labcomm_sig_parser_t *b, size_t n) {
194
195
196
	b->idx+=n;
}

197
unsigned int peek_varint(labcomm_sig_parser_t *b, unsigned char *size) {
Sven Robertz's avatar
Sven Robertz committed
198
        return unpack_varint(b->c, b->idx, size);
199
200
}

201
unsigned int get_varint(labcomm_sig_parser_t *b) {
Sven Robertz's avatar
Sven Robertz committed
202
203
204
205
        unsigned char size;
        unsigned int res = peek_varint(b, &size);
        advancen(b, size);
        return res;
206
}
207
unsigned int get_varint_size(labcomm_sig_parser_t *b, unsigned char *size) {
Sven Robertz's avatar
Sven Robertz committed
208
209
210
        unsigned int res = peek_varint(b, size);
        advancen(b, *size);
        return res;
211
212
}

213
void getStr(labcomm_sig_parser_t *b, char *dest, size_t size) {
214
215
216
217
218
219
220
	int rem = b->size - b->idx;
	if( size > rem ) 
		size = rem;
	strncpy(dest, &b->c[b->idx], size);
	b->idx += size;
}

221
labcomm_signature_t *get_sig_t(labcomm_sig_parser_t *p, unsigned int uid) 
222
{
223
	return &(p->sig_ts[uid-LABCOMM_USER]);
224
225
}

226
unsigned int get_signature_len(labcomm_sig_parser_t *p, unsigned int uid){
227
	//return signatures_length[uid-LABCOMM_USER];
228
	return p->sig_ts[uid-LABCOMM_USER].size;
229
}
230
unsigned char* get_signature(labcomm_sig_parser_t *p, unsigned int uid){
231
	//return signatures[uid-LABCOMM_USER];
232
	return p->sig_ts[uid-LABCOMM_USER].signature;
233
234
}

235
//is this needed?
236
//unsigned int get_signature_name_len(labcomm_sig_parser_t *p, unsigned int uid){
237
238
//	return signatures_name_length[uid-LABCOMM_USER];
//}
239

240
unsigned char* get_signature_name(labcomm_sig_parser_t *p, unsigned int uid){
241
	//return signatures_name[uid-LABCOMM_USER];
242
	return p->sig_ts[uid-LABCOMM_USER].name;
243
244
}

245
void dump_signature(labcomm_sig_parser_t *p, unsigned int uid){
246
	int i;
247
248
249
	unsigned int len = get_signature_len(p, uid);
	printf("signature for uid %x : %s (len=%d):\n", uid, get_signature_name(p, uid), len);
	unsigned char* sig = get_signature(p, uid);
250
251
	for(i=0; i<len; i++) {
		printf("%2.2x ",sig[i]);
252
		if( i < len-1 && (i+1)%8==0 ) printf("\n");
253
254
255
256
	}
	printf("\n");
}

257
static inline void labcomm_sig_parser_t_set_varsize(labcomm_sig_parser_t *b)
258
259
260
{
	b->current_decl_is_varsize = TRUE;
}
261
static size_t labcomm_sizeof_primitive(unsigned int type)
262
263
264
265
266
267
268
269
270
271
272
273
274
275
{
	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:
276
277
			printf("labcomm_sizeof_primitive(%x)\n", type);
		 	error("labcomm_sizeof_primitive should only be called for primitive types");
278
279
280
	}
}

281
//these are inlined in do_accept_packet
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
//static int accept_type_decl(labcomm_sig_parser_t *d);
//static int accept_sample_decl(labcomm_sig_parser_t *d);
static int accept_user_id(labcomm_sig_parser_t *d);
static int accept_string(labcomm_sig_parser_t *d);
static int accept_string_length(labcomm_sig_parser_t *d);
static int accept_char(labcomm_sig_parser_t *d);
static int accept_type(labcomm_sig_parser_t *d);
static int accept_array_decl(labcomm_sig_parser_t *d);
static int accept_number_of_indices(labcomm_sig_parser_t *d);
static int accept_indices(labcomm_sig_parser_t *d);
static int accept_variable_index(labcomm_sig_parser_t *d);
static int accept_fixed_index(labcomm_sig_parser_t *d);
static int accept_struct_decl(labcomm_sig_parser_t *d);
static int accept_number_of_fields(labcomm_sig_parser_t *d);
static int accept_field(labcomm_sig_parser_t *d);
static int accept_sample_data(labcomm_sig_parser_t *d);
298

Sven Robertz's avatar
Sven Robertz committed
299
300
301
302
303
304
305
306
307
308
309
310
static unsigned char labcomm_varint_sizeof(unsigned int i)
{
	if(i < 128) {
		return 1;
	} else {
		unsigned char res = 1;
		while (i >>= 7) ++res;

		return res;
	}
}

311
312
int encoded_size_static(labcomm_signature_t *sig, void *unused)
{
313
	if(sig->cached_encoded_size == -1) {
314
		error("encoded_size_static called for var_size sample or uninitialized signature");
315
	}
316
	return sig->cached_encoded_size;
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
}

/* This function probably never will be implemented, as it would be 
   similar to skip_packed_sample_data. And if unregistered variable size 
   samples is to be handled, the proper way is to generate and register
   a handler. Thus, the most probable use of the encoded_size function
   on the receiver side, is to skip unhandled samples.
*/
  
int encoded_size_parse_sig(labcomm_signature_t *sig, void *sample)
{
	printf("Warning: encoded_size_parse_sig not implemented\n");
	return -1;
}

332
333
334
335
336
337
338
339
340
341
342
343
344
345
static int accept_signature(labcomm_sig_parser_t *d)
{
	if(accept_user_id(d)) {
		unsigned int uid = pop_val(d);
		unsigned int nstart = d->idx;
		VERBOSE_PRINTF(", name = ");
		accept_string(d);
		unsigned int start = d->idx;
		unsigned int nlen = pop_val(d);
#ifdef RETURN_STRINGS
		char *str = (char *) pop_ptr(d);
		free(str);
#endif
		unsigned char lenlen = labcomm_varint_sizeof(nlen);
346
		VERBOSE_PRINTF("\ntype = ");
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
		accept_type(d);
		//printf(" : ");
		//unsigned int dt = pop(d);
		unsigned int type = pop_val(d);
		unsigned int enc_size = pop_val(d);
		unsigned int end = d->idx;
		unsigned int len = end-start;

		labcomm_signature_t *newsig = get_sig_t(d, uid);
		newsig->type = type;
		if(len <= d->max_sig_len) {
			d->signatures_length[uid-LABCOMM_USER] = len;
			memcpy(d->signatures[uid-LABCOMM_USER], &d->c[start], len);
			newsig->size = len;
			newsig->signature = d->signatures[uid-LABCOMM_USER];
		} else {
			error("sig longer than max length (this ought to be dynamic...)");
		}

		if(nlen < d->max_name_len) { // leave 1 byte for terminating NULL
			d->signatures_name_length[uid-LABCOMM_USER] = nlen;
			memcpy(d->signatures_name[uid-LABCOMM_USER], &d->c[nstart+lenlen], nlen);
			d->signatures_name[uid-LABCOMM_USER][nlen]=0;
			newsig->name = d->signatures_name[uid-LABCOMM_USER];
		} else {
			error("sig name longer than max length (this ought to be dynamic...");
		}
374
		VERBOSE_PRINTF("signature for uid %x: %s (start=%x,end=%x, nlen=%d,len=%d)\n", uid, get_signature_name(d, uid), start,end, nlen, len);
375
376
377
378
379
380
381
382
383
384
385
386
		INFO_PRINTF("SIG: %s\n", newsig->name);	
		if(! d->current_decl_is_varsize) {
			newsig->cached_encoded_size = enc_size;
			newsig->encoded_size = encoded_size_static;
			INFO_PRINTF(".... is static size = %d\n", enc_size);
		} else {
			newsig->cached_encoded_size = -1;
			newsig->encoded_size = encoded_size_parse_sig;
			INFO_PRINTF(".... is variable size\n");
		}
		return TRUE;
	} else {
387
		error("sample_decl with uid < LABCOMM_USER");	
388
389
390
391
		return FALSE;
	}
}

392
// HERE BE DRAGONS! what does the return value mean?
393
int accept_packet(labcomm_sig_parser_t *d) {
Sven Robertz's avatar
Sven Robertz committed
394
395
        unsigned char nbytes;
        unsigned int type = peek_varint(d, &nbytes) ;
396
	if(type == TYPE_DECL ) {
397
		//XXX is this used? If so, is it correct?
Sven Robertz's avatar
Sven Robertz committed
398
		advancen(d, nbytes);
399
400
401
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
		VERBOSE_PRINTF("type_decl ");
		accept_signature(d);
402
	} else if (type == SAMPLE_DECL) {
403
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
Sven Robertz's avatar
Sven Robertz committed
404
		advancen(d, nbytes);
405
		VERBOSE_PRINTF("sample_decl ");
406
		accept_signature(d);
407
	} else if(type >= LABCOMM_USER) {
408
#ifdef EXIT_WHEN_RECEIVING_DATA
409
410
		printf("*** got sample data, exiting\n");
		exit(0);
411
412
413
#else
		accept_sample_data(d);
#endif
414
	} else {
415
		error("got unknown type (<LABCOMM_USER)");
416
		exit(1);
417
418
419
	}
}

420
static int accept_user_id(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
421
422
423
424
        unsigned char nbytes;
	unsigned int uid = peek_varint(d, &nbytes);
	if(uid >= LABCOMM_USER) {
		advancen(d, nbytes);
425
		VERBOSE_PRINTF("uid = %x ", uid);
426
		push_val(d, uid);
427
428
429
430
431
432
		return TRUE;
	} else {
		return FALSE;
	}
}

433
static int accept_string(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
434
	unsigned int len = get_varint(d);
435
	char *str=malloc(len);
436
437
	getStr(d, str, len); 
	VERBOSE_PRINTF("%s", str);
438
#ifdef RETURN_STRINGS
439
	push_ptr(d, str);
440
441
442
#else
	free(str);
#endif
443
	push_val(d, len);
444
445
	return TRUE;
}
Sven Robertz's avatar
Sven Robertz committed
446
/* pushes size and type id */
447
static int accept_type(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
448
449
	unsigned char nbytes;
        unsigned int type = peek_varint(d, &nbytes) ;
450
451
	switch(type) {
		case TYPE_BOOLEAN :
452
			VERBOSE_PRINTF("boolean\n");
Sven Robertz's avatar
Sven Robertz committed
453
			advancen(d, nbytes);
454
			push_val(d, 1);
455
456
			break;
		case TYPE_BYTE :
457
			VERBOSE_PRINTF("byte\n");
Sven Robertz's avatar
Sven Robertz committed
458
			advancen(d, nbytes);
459
			push_val(d,  1);
460
461
			break;
		case TYPE_SHORT :
462
			VERBOSE_PRINTF("short\n");
Sven Robertz's avatar
Sven Robertz committed
463
			advancen(d, nbytes);
464
			push_val(d,  2);
465
466
			break;
		case TYPE_INTEGER :
467
			VERBOSE_PRINTF("integer\n");
Sven Robertz's avatar
Sven Robertz committed
468
			advancen(d, nbytes);
469
			push_val(d,  4);
470
471
			break;
		case TYPE_LONG :
472
			VERBOSE_PRINTF("long\n");
Sven Robertz's avatar
Sven Robertz committed
473
			advancen(d, nbytes);
474
			push_val(d,  8);
475
476
			break;
		case TYPE_FLOAT :
477
			VERBOSE_PRINTF("float\n");
Sven Robertz's avatar
Sven Robertz committed
478
			advancen(d, nbytes);
479
			push_val(d,  4);
480
481
			break;
		case TYPE_DOUBLE :
482
			VERBOSE_PRINTF("double\n");
Sven Robertz's avatar
Sven Robertz committed
483
			advancen(d, nbytes);
484
			push_val(d,  8);
485
486
			break;
		case TYPE_STRING :
487
			VERBOSE_PRINTF("string\n");
Sven Robertz's avatar
Sven Robertz committed
488
			advancen(d, nbytes);
489
			labcomm_sig_parser_t_set_varsize(d);
490
			push_val(d, 0);
491
492
493
			break;
		case ARRAY_DECL :
			accept_array_decl(d);
Sven Robertz's avatar
Sven Robertz committed
494
495
			pop_val(d); // ignore element type
			// push(d, pop(d) is a NOP --> leave size on stack
496
497
498
			break;
		case STRUCT_DECL :
			accept_struct_decl(d);
Sven Robertz's avatar
Sven Robertz committed
499
			// push(d, pop(d) is a NOP --> leave size on stack
500
501
			break;
		default :
502
			printf("accept_type default (type==%x) should not happen\n", type);
503
			push_val(d, 0);
Sven Robertz's avatar
Sven Robertz committed
504
			push_val(d, type);
505
506
			return FALSE;
	}
507
	push_val(d, type);
508
509
510
	return TRUE;
}

Sven Robertz's avatar
Sven Robertz committed
511
/* pushes size and element type */
512
static int accept_array_decl(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
513
514
        unsigned char nbytes;
        unsigned int tid = peek_varint(d, &nbytes) ;
515
	if(tid == ARRAY_DECL) {
Sven Robertz's avatar
Sven Robertz committed
516
517
		advancen(d, nbytes);
		unsigned int nidx = get_varint(d);
518
		VERBOSE_PRINTF("%d dim array", nidx);
519
520
521
522
		int i;
		unsigned int numVar=0;
		unsigned int size=1;
		for(i=0; i<nidx; i++) {
Sven Robertz's avatar
Sven Robertz committed
523
			unsigned int idx = get_varint(d);
524
525
			if(idx == 0) {
				numVar++;
526
				VERBOSE_PRINTF("[_] ");
527
				labcomm_sig_parser_t_set_varsize(d);
528
			} else {
529
				VERBOSE_PRINTF("[%d] ", idx);
530
531
532
				size*=idx;
			}
		}
533
		VERBOSE_PRINTF(" of ");
534
		accept_type(d);
535
536
		unsigned int et= pop_val(d);  // type
		unsigned int es= pop_val(d);  // (encoded) size
537
538
539
540
541
#ifdef DEBUG
		printf("accept_array_decl: et = %x\n", et);
#endif
		if(numVar == 0) {
#ifdef DEBUG
542
			printf("size=%d, es=%d\n", size, es);
543
#endif
544
			push_val(d,  (size*es));
545
		} else {
Sven Robertz's avatar
Sven Robertz committed
546
547
//HERE BE DRAGONS! push a (non-) size for variable size arrays?
			push_val(d, 0);
548
		}
Sven Robertz's avatar
Sven Robertz committed
549
		push_val(d, et);
550
551
552
		return TRUE;
	} else {
		printf("accept_array_decl: type=%x, should not happen\n",tid);
553
554
		push_val(d, 0);
		push_val(d, tid);
555
556
557
		return FALSE;
	}
}
558
559

/* pushes size */
560
static int accept_struct_decl(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
561
562
	unsigned char nbytes;
        unsigned int tid = peek_varint(d, &nbytes) ;
563
	if(tid == STRUCT_DECL) {
Sven Robertz's avatar
Sven Robertz committed
564
565
		advancen(d, nbytes);
		unsigned int nf = get_varint(d);
566
		VERBOSE_PRINTF("%d field struct:\n", nf);
567
568
569
		int i;
		int numVar=0;
		int size=0;
570
		unsigned int fieldsizes=0;
571
572
		for(i=0; i<nf; i++) {
			accept_field(d);
573
			fieldsizes += pop_val(d);
574
		}
575
		push_val(d, fieldsizes);
576
577
578
		return TRUE;
	} else {
		printf("accept_struct_decl: type=%x, should not happen\n",tid);
579
		push_val(d, 0);
580
581
582
		return FALSE;
	}
}
583

Sven Robertz's avatar
Sven Robertz committed
584
/* pushes field size */
585
static int accept_field(labcomm_sig_parser_t *d){
586
	VERBOSE_PRINTF("\tfield name: ");
587
	accept_string(d);
588
	pop_val(d); // ignore length, for now
Sven Robertz's avatar
Sven Robertz committed
589
#ifdef RETURN_STRINGS
590
		char *str = (char *) pop_ptr(d);
Sven Robertz's avatar
Sven Robertz committed
591
592
		free(str);
#endif
593
	VERBOSE_PRINTF("\n\ttype: ");
594
	accept_type(d);
595
	pop_val(d); // ignore type, for now
Sven Robertz's avatar
Sven Robertz committed
596
	// push(pop() is really a NOP , leave size on the stack when debugging done
597
	VERBOSE_PRINTF("\n");
598
}
599
static int accept_sample_data(labcomm_sig_parser_t *d){
600
	accept_user_id(d);
601
	unsigned int uid = pop_val(d);	
602
	printf("sample data... uid=0x%x\n", uid);
603
#ifdef DEBUG
604
	dump_signature(d, uid);
605
#endif
606
	labcomm_signature_t *sigt = get_sig_t(d, uid);
607
608
	int encoded_size = sigt->encoded_size(sigt, NULL);
	INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
609
	labcomm_signature_t *sig = get_sig_t(d, uid);
610
	skip_packed_sample_data(d, sig);
611
612
613
	return TRUE;
}

614
static int skip_type(unsigned int,labcomm_sig_parser_t*,unsigned char*,unsigned int,unsigned int*) ;
615

616
static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
617
618
	unsigned int skip = 0;
	unsigned int tot_nbr_elem_tmp = 1;
Sven Robertz's avatar
Sven Robertz committed
619
620
	unsigned char nbytes;
	unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
621
	VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
Sven Robertz's avatar
Sven Robertz committed
622
	*pos +=nbytes;
623
624
625
626
627
628
	unsigned int idx[nIdx];
	unsigned int nVar=0;

	unsigned int i;

	for(i=0; i<nIdx; i++) {
Sven Robertz's avatar
Sven Robertz committed
629
630
		idx[i] = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
631
		VERBOSE_PRINTF("skip_array: idx[%d]=%d (from sig)\n", i, idx[i]);
632
633
634
635
636
637
638
639
		if(idx[i] == 0) {
			nVar++;
		} else {
			tot_nbr_elem_tmp *= idx[i];
		}
	}
	unsigned int var[nVar];

Sven Robertz's avatar
Sven Robertz committed
640
	unsigned char varSize=0; // total number of bytes required for var size fields
641
	for(i=0; i<nVar; i++) {
Sven Robertz's avatar
Sven Robertz committed
642
643
		var[i] = get_varint_size(d, &nbytes);	
		varSize += nbytes;
644
		VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
Sven Robertz's avatar
Sven Robertz committed
645
		tot_nbr_elem_tmp *= var[i];
646
647
	}

Sven Robertz's avatar
Sven Robertz committed
648
649
	unsigned int type = unpack_varint(sig, *pos, &nbytes);
	*pos+=nbytes;
650

651
	unsigned int elemSize = labcomm_sizeof_primitive(type);
652
653
654

	skip = elemSize * tot_nbr_elem_tmp;

655
	VERBOSE_PRINTF("skip_array: skip: %d * %d = %d\n", tot_nbr_elem_tmp, elemSize ,skip);
656
657
658
	
	advancen(d, skip);

Sven Robertz's avatar
Sven Robertz committed
659
660
	//return skip + 4*nVar;
	return skip + varSize;
661
662
}

663
int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
Sven Robertz's avatar
Sven Robertz committed
664
665
666
	unsigned char nbytes;
	unsigned int nFields = unpack_varint(sig,*pos, &nbytes);
	*pos += nbytes;
667
668
	unsigned int i;
	unsigned int skipped=0;
669
	VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
670
671
	for(i=0; i<nFields; i++) {
		//skip name 
Sven Robertz's avatar
Sven Robertz committed
672
		unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
673
#ifdef DEBUG
674
		VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
Sven Robertz's avatar
Sven Robertz committed
675
		char name[namelen+1]; //HERE BE DRAGONS. alloca?
Sven Robertz's avatar
Sven Robertz committed
676
		strncpy(name, sig+*pos+nbytes, namelen);
677
		name[namelen]=0;
678
		VERBOSE_PRINTF("----name = %s\n",name);
679
#endif
Sven Robertz's avatar
Sven Robertz committed
680
		*pos += (nbytes+namelen); // 32bit len + actual string
Sven Robertz's avatar
Sven Robertz committed
681

Sven Robertz's avatar
Sven Robertz committed
682
683
		unsigned int type = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
684
#ifdef DEBUG
685
		VERBOSE_PRINTF("----type == %x\n", type);
686
687
688
689
690
691
692
#endif
		skipped += skip_type(type, d, sig, len, pos);
	}
	return skipped;
}
#ifndef QUIET
/* print and skip */
693
int skip_type(unsigned int type, labcomm_sig_parser_t *d, 
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
		unsigned char *sig, unsigned int len, unsigned int *pos) 
{
	int skipped=0;
	printf("skip_type %x:", type);
	switch(type) {
		case TYPE_BOOLEAN :
			printf("boolean [%d]\n", get(d));
			skipped++;
			break;
		case TYPE_BYTE : 
			printf("byte [%d]\n", get(d));
			skipped++;
			break;
		case TYPE_SHORT : 
			//XXX not supported
			advancen(d,2); 
			skipped+=2;
			break;
		case TYPE_INTEGER :
			printf("integer [%d]\n", get32(d));
			skipped +=4;
			break;
		case TYPE_FLOAT : 
			//XXX not supported
			advancen(d,4); 
			skipped+=4;
			break;
		case TYPE_LONG :
		case TYPE_DOUBLE : 
			//XXX not supported
			advancen(d,8); 
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
728
729
730
			{
			unsigned char nbytes;
			unsigned int len = get_varint_size(d, &nbytes);
731
732
733
734
735
			int i;
			printf("string [");
			for(i=0; i<len; i++)
				printf("%c", get(d));
			printf("]\n");
Sven Robertz's avatar
Sven Robertz committed
736
			skipped+=len+nbytes;
737
738
739
740
			break;}
		case ARRAY_DECL :
			printf("array\n");
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
741
			break;
742
743
744
745
746
747
748
749
750
751
752
		case STRUCT_DECL :
			printf("struct\n");
			skipped += skip_struct(d, sig, len, pos);
			break;
		default:
			printf("ERROR: skip_type: type = %x\n", type);
			exit(1);
	}
	return skipped;
}
#else
753
int skip_type(unsigned int type, labcomm_sig_parser_t *d, 
754
755
756
		unsigned char *sig, unsigned int len, unsigned int *pos) 
{
	int skipped=0;
757
	VERBOSE_PRINTF("skip_type %x\n", type);
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
	switch(type) {
		case TYPE_BOOLEAN :
		case TYPE_BYTE : 
			advancen(d,1); 
			skipped++;
			break;
		case TYPE_SHORT : 
			advancen(d,2); 
			skipped+=2;
			break;
		case TYPE_INTEGER :
		case TYPE_FLOAT : 
			advancen(d,4); 
			skipped+=4;
			break;
		case TYPE_LONG :
		case TYPE_DOUBLE : 
			advancen(d,8); 
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
779
780
781
			{
			unsigned char nbytes;
			unsigned int len = get_varint_size(d, &nbytes);
782
			advancen(d,len);
Sven Robertz's avatar
Sven Robertz committed
783
			skipped+=len+nbytes;
784
785
786
			break;}
		case ARRAY_DECL :
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
787
			break;
788
789
790
791
792
793
794
795
796
797
798
		case STRUCT_DECL :
			skipped += skip_struct(d, sig, len, pos);
			break;
		default:
			printf("ERROR: skip_type: type = %x\n", type);
			exit(1);
	}
	return skipped;
}
#endif

799
/* parse signature and skip the corresponding bytes in the labcomm_sig_parser_t 
800
 */
801
int skip_packed_sample_data(labcomm_sig_parser_t *d, labcomm_signature_t *sig) {
802
803
	unsigned int pos = 0; 		//current position in signature
	unsigned int skipped = 0;	//skipped byte counter
804
	while(pos < sig->size) {
Sven Robertz's avatar
Sven Robertz committed
805
		unsigned char nbytes;
806
		unsigned int type = unpack_varint(sig->signature,pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
807
		pos+=nbytes;
808
		skipped += skip_type(type, d, sig->signature, sig->size, &pos);
809
810
811
812
	}	
	printf("skipped %d bytes\n", skipped);
	return TRUE;
}