1 /*
2  * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #ifndef LV2_OSC_READER_H
19 #define LV2_OSC_READER_H
20 
21 #include <stdbool.h>
22 #include <string.h>
23 #include <stdarg.h>
24 
25 #include <osc.lv2/osc.h>
26 #include <osc.lv2/endian.h>
27 #include <osc.lv2/util.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 
34 typedef struct _LV2_OSC_Tree LV2_OSC_Tree;
35 typedef struct _LV2_OSC_Reader LV2_OSC_Reader;
36 typedef struct _LV2_OSC_Item LV2_OSC_Item;
37 typedef struct _LV2_OSC_Arg LV2_OSC_Arg;
38 typedef void (*LV2_OSC_Branch)(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg,
39 	const LV2_OSC_Tree *tree, void *data);
40 
41 struct _LV2_OSC_Tree {
42 	const char *name;
43 	const LV2_OSC_Tree *trees;
44 	LV2_OSC_Branch branch;
45 };
46 
47 struct _LV2_OSC_Reader {
48 	const uint8_t *buf;
49 	const uint8_t *ptr;
50 	const uint8_t *end;
51 };
52 
53 struct _LV2_OSC_Item {
54 	int32_t size;
55 	const uint8_t *body;
56 
57 	uint64_t timetag;
58 	const uint8_t *end;
59 };
60 
61 struct _LV2_OSC_Arg {
62 	const char *type;
63 	int32_t size;
64 	union {
65 		int32_t i;
66 		float f;
67 		const char *s;
68 		const uint8_t *b;
69 
70 		int64_t h;
71 		double d;
72 		uint64_t t;
73 
74 		const uint8_t *m;
75 		const char *S;
76 		char c;
77 		struct {
78 			uint8_t R;
79 			uint8_t G;
80 			uint8_t B;
81 			uint8_t A;
82 		}; // anonymous RGBA struct
83 	};
84 
85 	const char *path;
86 	const uint8_t *end;
87 };
88 
89 static inline void
lv2_osc_reader_initialize(LV2_OSC_Reader * reader,const uint8_t * buf,size_t size)90 lv2_osc_reader_initialize(LV2_OSC_Reader *reader, const uint8_t *buf, size_t size)
91 {
92 	reader->buf = buf;
93 	reader->ptr = buf;
94 	reader->end = buf + size;
95 }
96 
97 static inline bool
lv2_osc_reader_overflow(LV2_OSC_Reader * reader,size_t size)98 lv2_osc_reader_overflow(LV2_OSC_Reader *reader, size_t size)
99 {
100 	return reader->ptr + size > reader->end;
101 }
102 
103 static inline bool
lv2_osc_reader_be32toh(LV2_OSC_Reader * reader,union swap32_t * s32)104 lv2_osc_reader_be32toh(LV2_OSC_Reader *reader, union swap32_t *s32)
105 {
106 	if(lv2_osc_reader_overflow(reader, 4))
107 		return false;
108 
109 	s32->u = *(const uint32_t *)reader->ptr;
110 	s32->u = be32toh(s32->u);
111 	reader->ptr += 4;
112 
113 	return true;
114 }
115 
116 static inline bool
lv2_osc_reader_be64toh(LV2_OSC_Reader * reader,union swap64_t * s64)117 lv2_osc_reader_be64toh(LV2_OSC_Reader *reader, union swap64_t *s64)
118 {
119 	if(lv2_osc_reader_overflow(reader, 8))
120 		return false;
121 
122 	s64->u = *(const uint64_t *)reader->ptr;
123 	s64->u = be64toh(s64->u);
124 	reader->ptr += 8;
125 
126 	return true;
127 }
128 
129 static inline bool
lv2_osc_reader_get_int32(LV2_OSC_Reader * reader,int32_t * i)130 lv2_osc_reader_get_int32(LV2_OSC_Reader *reader, int32_t *i)
131 {
132 	union swap32_t s32;
133 	if(!lv2_osc_reader_be32toh(reader, &s32))
134 		return false;
135 
136 	*i = s32.i;
137 
138 	return true;
139 }
140 
141 static inline bool
lv2_osc_reader_get_float(LV2_OSC_Reader * reader,float * f)142 lv2_osc_reader_get_float(LV2_OSC_Reader *reader, float *f)
143 {
144 	union swap32_t s32;
145 	if(!lv2_osc_reader_be32toh(reader, &s32))
146 		return false;
147 
148 	*f = s32.f;
149 
150 	return true;
151 }
152 
153 static inline bool
lv2_osc_reader_get_int64(LV2_OSC_Reader * reader,int64_t * h)154 lv2_osc_reader_get_int64(LV2_OSC_Reader *reader, int64_t *h)
155 {
156 	union swap64_t s64;
157 	if(!lv2_osc_reader_be64toh(reader, &s64))
158 		return false;
159 
160 	*h = s64.h;
161 
162 	return true;
163 }
164 
165 static inline bool
lv2_osc_reader_get_timetag(LV2_OSC_Reader * reader,uint64_t * t)166 lv2_osc_reader_get_timetag(LV2_OSC_Reader *reader, uint64_t *t)
167 {
168 	union swap64_t s64;
169 	if(!lv2_osc_reader_be64toh(reader, &s64))
170 		return false;
171 
172 	*t = s64.u;
173 
174 	return true;
175 }
176 
177 static inline bool
lv2_osc_reader_get_double(LV2_OSC_Reader * reader,double * d)178 lv2_osc_reader_get_double(LV2_OSC_Reader *reader, double *d)
179 {
180 	union swap64_t s64;
181 	if(!lv2_osc_reader_be64toh(reader, &s64))
182 		return false;
183 
184 	*d = s64.d;
185 
186 	return true;
187 }
188 
189 static inline bool
lv2_osc_reader_get_string(LV2_OSC_Reader * reader,const char ** s)190 lv2_osc_reader_get_string(LV2_OSC_Reader *reader, const char **s)
191 {
192 	const char *str = (const char *)reader->ptr;
193 	const size_t padded = LV2_OSC_PADDED_SIZE(strlen(str) + 1);
194 	if(lv2_osc_reader_overflow(reader, padded ))
195 		return false;
196 
197 	*s = str;
198 	reader->ptr += padded;
199 
200 	return true;
201 }
202 
203 static inline bool
lv2_osc_reader_get_symbol(LV2_OSC_Reader * reader,const char ** S)204 lv2_osc_reader_get_symbol(LV2_OSC_Reader *reader, const char **S)
205 {
206 	return lv2_osc_reader_get_string(reader, S);
207 }
208 
209 static inline bool
lv2_osc_reader_get_midi(LV2_OSC_Reader * reader,const uint8_t ** m)210 lv2_osc_reader_get_midi(LV2_OSC_Reader *reader, const uint8_t **m)
211 {
212 	if(lv2_osc_reader_overflow(reader, 4))
213 		return false;
214 
215 	*m = reader->ptr;
216 	reader->ptr += 4;
217 
218 	return true;
219 }
220 
221 static inline bool
lv2_osc_reader_get_blob(LV2_OSC_Reader * reader,int32_t * len,const uint8_t ** body)222 lv2_osc_reader_get_blob(LV2_OSC_Reader *reader, int32_t *len, const uint8_t **body)
223 {
224 	if(!lv2_osc_reader_get_int32(reader, len))
225 		return false;
226 
227 	const size_t padded = LV2_OSC_PADDED_SIZE(*len);
228 	if(lv2_osc_reader_overflow(reader, padded))
229 		return false;
230 
231 	*body = reader->ptr;
232 	reader->ptr += padded;
233 
234 	return true;
235 }
236 
237 static inline bool
lv2_osc_reader_get_rgba(LV2_OSC_Reader * reader,uint8_t * r,uint8_t * g,uint8_t * b,uint8_t * a)238 lv2_osc_reader_get_rgba(LV2_OSC_Reader *reader, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a)
239 {
240 	if(lv2_osc_reader_overflow(reader, 4))
241 		return false;
242 
243 	*r = reader->ptr[0];
244 	*g = reader->ptr[1];
245 	*b = reader->ptr[2];
246 	*a = reader->ptr[3];
247 	reader->ptr += 4;
248 
249 	return true;
250 }
251 
252 static inline bool
lv2_osc_reader_get_char(LV2_OSC_Reader * reader,char * c)253 lv2_osc_reader_get_char(LV2_OSC_Reader *reader, char *c)
254 {
255 	int32_t i;
256 	if(!lv2_osc_reader_get_int32(reader, &i))
257 		return false;
258 
259 	*c = i;
260 
261 	return true;
262 }
263 
264 static inline LV2_OSC_Item *
lv2_osc_reader_item_raw(LV2_OSC_Reader * reader,LV2_OSC_Item * itm)265 lv2_osc_reader_item_raw(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
266 {
267 	if(!lv2_osc_reader_get_int32(reader, &itm->size))
268 		return NULL;
269 
270 	if(lv2_osc_reader_overflow(reader, itm->size))
271 		return NULL;
272 
273 	itm->body = reader->ptr;
274 
275 	return itm;
276 }
277 
278 static inline LV2_OSC_Item *
lv2_osc_reader_item_begin(LV2_OSC_Reader * reader,LV2_OSC_Item * itm,size_t len)279 lv2_osc_reader_item_begin(LV2_OSC_Reader *reader, LV2_OSC_Item *itm, size_t len)
280 {
281 	if(lv2_osc_reader_overflow(reader, len))
282 		return NULL;
283 
284 	itm->end = reader->ptr + len;
285 
286 	if(lv2_osc_reader_overflow(reader, 16))
287 		return NULL;
288 
289 	if(strncmp((const char *)reader->ptr, "#bundle", 8))
290 		return NULL;
291 	reader->ptr += 8;
292 
293 	if(!lv2_osc_reader_get_timetag(reader, &itm->timetag))
294 		return NULL;
295 
296 	return lv2_osc_reader_item_raw(reader, itm);
297 }
298 
299 static inline bool
lv2_osc_reader_item_is_end(LV2_OSC_Reader * reader,LV2_OSC_Item * itm)300 lv2_osc_reader_item_is_end(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
301 {
302 	return reader->ptr > itm->end;
303 }
304 
305 static inline LV2_OSC_Item *
lv2_osc_reader_item_next(LV2_OSC_Reader * reader,LV2_OSC_Item * itm)306 lv2_osc_reader_item_next(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
307 {
308 	reader->ptr += itm->size;
309 
310 	return lv2_osc_reader_item_raw(reader, itm);
311 }
312 
313 #define OSC_READER_BUNDLE_BEGIN(reader, len) \
314 	lv2_osc_reader_item_begin( \
315 		(reader), \
316 		&(LV2_OSC_Item){ .size = 0, .body = NULL, .timetag = 1ULL, .end = NULL }, \
317 		len)
318 
319 #define OSC_READER_BUNDLE_ITERATE(reader, itm) \
320 	for(itm = itm; \
321 		itm && !lv2_osc_reader_item_is_end((reader), (itm)); \
322 		itm = lv2_osc_reader_item_next((reader), (itm)))
323 
324 #define OSC_READER_BUNDLE_FOREACH(reader, itm, len) \
325 	for(LV2_OSC_Item *(itm) = OSC_READER_BUNDLE_BEGIN((reader), (len)); \
326 		itm && !lv2_osc_reader_item_is_end((reader), (itm)); \
327 		itm = lv2_osc_reader_item_next((reader), (itm)))
328 
329 static inline LV2_OSC_Arg *
lv2_osc_reader_arg_raw(LV2_OSC_Reader * reader,LV2_OSC_Arg * arg)330 lv2_osc_reader_arg_raw(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
331 {
332 	switch( (LV2_OSC_Type)*arg->type)
333 	{
334 		case LV2_OSC_INT32:
335 		{
336 			if(!lv2_osc_reader_get_int32(reader, &arg->i))
337 				return NULL;
338 			arg->size = 4;
339 
340 			break;
341 		}
342 		case LV2_OSC_FLOAT:
343 		{
344 			if(!lv2_osc_reader_get_float(reader, &arg->f))
345 				return NULL;
346 			arg->size = 4;
347 
348 			break;
349 		}
350 		case LV2_OSC_STRING:
351 		{
352 			if(!lv2_osc_reader_get_string(reader, &arg->s))
353 				return NULL;
354 			arg->size = strlen(arg->s) + 1;
355 
356 			break;
357 		}
358 		case LV2_OSC_BLOB:
359 		{
360 			if(!lv2_osc_reader_get_blob(reader, &arg->size, &arg->b))
361 				return NULL;
362 			//arg->size = arg->size;
363 
364 			break;
365 		}
366 
367 		case LV2_OSC_TRUE:
368 		case LV2_OSC_FALSE:
369 		case LV2_OSC_NIL:
370 		case LV2_OSC_IMPULSE:
371 			break;
372 
373 		case LV2_OSC_INT64:
374 		{
375 			if(!lv2_osc_reader_get_int64(reader, &arg->h))
376 				return NULL;
377 			arg->size = 8;
378 
379 			break;
380 		}
381 		case LV2_OSC_DOUBLE:
382 		{
383 			if(!lv2_osc_reader_get_double(reader, &arg->d))
384 				return NULL;
385 			arg->size = 8;
386 
387 			break;
388 		}
389 		case LV2_OSC_TIMETAG:
390 		{
391 			if(!lv2_osc_reader_get_timetag(reader, &arg->t))
392 				return NULL;
393 			arg->size = 8;
394 
395 			break;
396 		}
397 
398 		case LV2_OSC_MIDI:
399 		{
400 			if(!lv2_osc_reader_get_midi(reader, &arg->m))
401 				return NULL;
402 			arg->size = 4;
403 
404 			break;
405 		}
406 		case LV2_OSC_SYMBOL:
407 		{
408 			if(!lv2_osc_reader_get_symbol(reader, &arg->S))
409 				return NULL;
410 			arg->size = strlen(arg->S) + 1;
411 
412 			break;
413 		}
414 		case LV2_OSC_CHAR:
415 		{
416 			if(!lv2_osc_reader_get_char(reader, &arg->c))
417 				return NULL;
418 			arg->size = 4;
419 
420 			break;
421 		}
422 		case LV2_OSC_RGBA:
423 		{
424 			if(!lv2_osc_reader_get_rgba(reader, &arg->R, &arg->G, &arg->B, &arg->A))
425 				return NULL;
426 			arg->size = 4;
427 
428 			break;
429 		}
430 	}
431 
432 	return arg;
433 }
434 
435 static inline LV2_OSC_Arg *
lv2_osc_reader_arg_begin(LV2_OSC_Reader * reader,LV2_OSC_Arg * arg,size_t len)436 lv2_osc_reader_arg_begin(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg, size_t len)
437 {
438 	if(lv2_osc_reader_overflow(reader, len))
439 		return NULL;
440 
441 	arg->end = reader->ptr + len;
442 
443 	if(!lv2_osc_reader_get_string(reader, &arg->path)) //TODO check for validity
444 		return NULL;
445 
446 	if(!lv2_osc_reader_get_string(reader, &arg->type)) //TODO check for validity
447 		return NULL;
448 
449 	if(*arg->type != ',')
450 		return NULL;
451 
452 	arg->type++; // skip ','
453 
454 	return lv2_osc_reader_arg_raw(reader, arg);
455 }
456 
457 static inline bool
lv2_osc_reader_arg_is_end(LV2_OSC_Reader * reader,LV2_OSC_Arg * arg)458 lv2_osc_reader_arg_is_end(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
459 {
460 	return (*arg->type == '\0') || (reader->ptr > arg->end);
461 }
462 
463 static inline LV2_OSC_Arg *
lv2_osc_reader_arg_next(LV2_OSC_Reader * reader,LV2_OSC_Arg * arg)464 lv2_osc_reader_arg_next(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
465 {
466 	arg->type++;
467 
468 	return lv2_osc_reader_arg_raw(reader, arg);
469 }
470 
471 #define OSC_READER_MESSAGE_BEGIN(reader, len) \
472 	lv2_osc_reader_arg_begin( \
473 		(reader), \
474 		&(LV2_OSC_Arg){ .type = NULL, .size = 0, .path = NULL, .end = NULL }, \
475 		len)
476 
477 #define OSC_READER_MESSAGE_ITERATE(reader, arg) \
478 	for(arg = arg; \
479 		arg && !lv2_osc_reader_arg_is_end((reader), (arg)); \
480 		arg = lv2_osc_reader_arg_next((reader), (arg)))
481 
482 #define OSC_READER_MESSAGE_FOREACH(reader, arg, len) \
483 	for(LV2_OSC_Arg *(arg) = OSC_READER_MESSAGE_BEGIN((reader), (len)); \
484 		arg && !lv2_osc_reader_arg_is_end((reader), (arg)); \
485 		arg = lv2_osc_reader_arg_next((reader), (arg)))
486 
487 static inline bool
lv2_osc_reader_arg_varlist(LV2_OSC_Reader * reader,const char * fmt,va_list args)488 lv2_osc_reader_arg_varlist(LV2_OSC_Reader *reader, const char *fmt, va_list args)
489 {
490 	for(const char *type = fmt; *type; type++)
491 	{
492 		switch( (LV2_OSC_Type)*type)
493 		{
494 			case LV2_OSC_INT32:
495 				if(!lv2_osc_reader_get_int32(reader, va_arg(args, int32_t *)))
496 					return false;
497 				break;
498 			case LV2_OSC_FLOAT:
499 				if(!lv2_osc_reader_get_float(reader, va_arg(args, float *)))
500 					return false;
501 				break;
502 			case LV2_OSC_STRING:
503 				if(!lv2_osc_reader_get_string(reader, va_arg(args, const char **)))
504 					return false;
505 				break;
506 			case LV2_OSC_BLOB:
507 				if(!lv2_osc_reader_get_blob(reader, va_arg(args, int32_t *), va_arg(args, const uint8_t **)))
508 					return false;
509 				break;
510 
511 			case LV2_OSC_TRUE:
512 			case LV2_OSC_FALSE:
513 			case LV2_OSC_NIL:
514 			case LV2_OSC_IMPULSE:
515 				break;
516 
517 			case LV2_OSC_INT64:
518 				if(!lv2_osc_reader_get_int64(reader, va_arg(args, int64_t *)))
519 					return false;
520 				break;
521 			case LV2_OSC_DOUBLE:
522 				if(!lv2_osc_reader_get_double(reader, va_arg(args, double *)))
523 					return false;
524 				break;
525 			case LV2_OSC_TIMETAG:
526 				if(!lv2_osc_reader_get_timetag(reader, va_arg(args, uint64_t *)))
527 					return false;
528 				break;
529 
530 			case LV2_OSC_MIDI:
531 				if(!lv2_osc_reader_get_midi(reader, va_arg(args, const uint8_t **)))
532 					return false;
533 				break;
534 			case LV2_OSC_SYMBOL:
535 				if(!lv2_osc_reader_get_symbol(reader, va_arg(args, const char **)))
536 					return false;
537 				break;
538 			case LV2_OSC_CHAR:
539 				if(!lv2_osc_reader_get_char(reader, va_arg(args, char *)))
540 					return false;
541 				break;
542 			case LV2_OSC_RGBA:
543 				if(!lv2_osc_reader_get_rgba(reader, va_arg(args, uint8_t *), va_arg(args, uint8_t *),
544 						va_arg(args, uint8_t *), va_arg(args, uint8_t *)))
545 					return false;
546 				break;
547 		}
548 	}
549 
550 	return true;
551 }
552 
553 static inline bool
lv2_osc_reader_arg_vararg(LV2_OSC_Reader * reader,const char * fmt,...)554 lv2_osc_reader_arg_vararg(LV2_OSC_Reader *reader, const char *fmt, ...)
555 {
556   va_list args;
557   va_start(args, fmt);
558 
559 	const bool res = lv2_osc_reader_arg_varlist(reader, fmt, args);
560 
561 	va_end(args);
562 
563 	return res;
564 }
565 
566 static inline bool
lv2_osc_reader_is_bundle(LV2_OSC_Reader * reader)567 lv2_osc_reader_is_bundle(LV2_OSC_Reader *reader)
568 {
569 	return strncmp((const char *)reader->ptr, "#bundle", 8) == 0;
570 }
571 
572 static inline bool
lv2_osc_reader_is_message(LV2_OSC_Reader * reader)573 lv2_osc_reader_is_message(LV2_OSC_Reader *reader)
574 {
575 	return reader->ptr[0] == '/'; //FIXME check path
576 }
577 
578 static inline void
_lv2_osc_trees_internal(LV2_OSC_Reader * reader,const char * path,const char * from,LV2_OSC_Arg * arg,const LV2_OSC_Tree * trees,void * data)579 _lv2_osc_trees_internal(LV2_OSC_Reader *reader, const char *path, const char *from,
580 	LV2_OSC_Arg *arg, const LV2_OSC_Tree *trees, void *data)
581 {
582 	const char *ptr = strchr(from, '/');
583 	const char *pattern = strpbrk(from, "*?[]{}/");
584 	const bool has_pattern = pattern && (pattern[0] != '/');
585 	(void)has_pattern; //FIXME
586 
587 	const size_t len = ptr
588 		? (size_t)(ptr - from)
589 		: strlen(from);
590 
591 	for(const LV2_OSC_Tree *tree = trees; tree && tree->name; tree++)
592 	{
593 		if(lv2_osc_pattern_match(from, tree->name, len))
594 		{
595 			if(tree->trees && ptr)
596 			{
597 				if(tree->branch)
598 				{
599 					LV2_OSC_Reader reader_clone = *reader;
600 					tree->branch(&reader_clone, arg, tree, data);
601 				}
602 
603 				_lv2_osc_trees_internal(reader, path, &ptr[1], arg, tree->trees, data);
604 			}
605 			else if(tree->branch && !ptr)
606 			{
607 				LV2_OSC_Reader reader_clone = *reader;
608 				tree->branch(&reader_clone, arg, tree, data);
609 			}
610 		}
611 	}
612 }
613 
614 static inline void
lv2_osc_reader_match(LV2_OSC_Reader * reader,size_t len,const LV2_OSC_Tree * trees,void * data)615 lv2_osc_reader_match(LV2_OSC_Reader *reader, size_t len,
616 	const LV2_OSC_Tree *trees, void *data)
617 {
618 	LV2_OSC_Arg *arg = OSC_READER_MESSAGE_BEGIN(reader, len);
619 	const char *path = arg->path;
620 	const char *from = &path[1];
621 
622 	_lv2_osc_trees_internal(reader, path, from, arg, trees, data);
623 }
624 
625 #ifdef __cplusplus
626 } // extern "C"
627 #endif
628 
629 #endif // LV2_OSC_READER_H
630