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