LMMS
Loading...
Searching...
No Matches
rtosc.c
Go to the documentation of this file.
1#include <stdint.h>
2#include <stdio.h>
3#include <string.h>
4#include <stdarg.h>
5#include <stdbool.h>
6#include <ctype.h>
7#include <assert.h>
8
9#include <rtosc/rtosc.h>
10
11const char *rtosc_argument_string(const char *msg)
12{
13 assert(msg && *msg);
14 while(*++msg); //skip pattern
15 while(!*++msg);//skip null
16 return msg+1; //skip comma
17}
18
19unsigned rtosc_narguments(const char *msg)
20{
21 const char *args = rtosc_argument_string(msg);
22 int nargs = 0;
23 while(*args++)
24 nargs += (*args == ']' || *args == '[') ? 0 : 1;
25 return nargs;
26}
27
28static int has_reserved(char type)
29{
30 switch(type)
31 {
32 case 'i'://official types
33 case 's':
34 case 'b':
35 case 'f':
36
37 case 'h'://unofficial
38 case 't':
39 case 'd':
40 case 'S':
41 case 'r':
42 case 'm':
43 case 'c':
44 return 1;
45 case 'T':
46 case 'F':
47 case 'N':
48 case 'I':
49 case '[':
50 case ']':
51 return 0;
52 }
53
54 //Should not happen
55 return 0;
56}
57
58static unsigned nreserved(const char *args)
59{
60 unsigned res = 0;
61 for(;*args;++args)
62 res += has_reserved(*args);
63
64 return res;
65}
66
67char rtosc_type(const char *msg, unsigned nargument)
68{
69 assert(nargument < rtosc_narguments(msg));
70 const char *arg = rtosc_argument_string(msg);
71 while(1) {
72 if(*arg == '[' || *arg == ']')
73 ++arg;
74 else if(!nargument || !*arg)
75 return *arg;
76 else
77 ++arg, --nargument;
78 }
79}
80
81static unsigned arg_start(const char *msg_)
82{
83 const uint8_t *msg = (const uint8_t*)msg_;
84 //Iterate to the right position
85 const uint8_t *args = (const uint8_t*) rtosc_argument_string(msg_);
86 const uint8_t *aligned_ptr = args-1;
87 const uint8_t *arg_pos = args;
88
89 while(*++arg_pos);
90 //Alignment
91 arg_pos += 4-(arg_pos-aligned_ptr)%4;
92 return arg_pos-msg;
93}
94
95static unsigned arg_size(const uint8_t *arg_mem, char type)
96{
97 if(!has_reserved(type))
98 return 0;
99 const uint8_t *arg_pos=arg_mem;
100 uint32_t blob_length = 0;
101 switch(type)
102 {
103 case 'h':
104 case 't':
105 case 'd':
106 return 8;
107 case 'm':
108 case 'r':
109 case 'f':
110 case 'c':
111 case 'i':
112 return 4;
113 case 'S':
114 case 's':
115 while(*++arg_pos);
116 arg_pos += 4-(arg_pos-arg_mem)%4;
117 return arg_pos-arg_mem;
118 case 'b':
119 blob_length |= (*arg_pos++ << 24);
120 blob_length |= (*arg_pos++ << 16);
121 blob_length |= (*arg_pos++ << 8);
122 blob_length |= (*arg_pos++);
123 if(blob_length%4)
124 blob_length += 4-blob_length%4;
125 arg_pos += blob_length;
126 return arg_pos-arg_mem;
127 default:
128 assert("Invalid Type");
129 }
130 return -1;
131}
132
133static unsigned arg_off(const char *msg, unsigned idx)
134{
135 if(!has_reserved(rtosc_type(msg,idx)))
136 return 0;
137
138 //Iterate to the right position
139 const uint8_t *args = (const uint8_t*) rtosc_argument_string(msg);
140 const uint8_t *aligned_ptr = args-1;
141 const uint8_t *arg_pos = args;
142
143 while(*++arg_pos);
144 //Alignment
145 arg_pos += 4-(arg_pos-((uint8_t*)aligned_ptr))%4;
146
147 //ignore any leading '[' or ']'
148 while(*args == '[' || *args == ']')
149 ++args;
150
151 while(idx--) {
152 char type = *args++;
153 if(type == '[' || type == ']')
154 idx++;//not a valid arg idx
155 else
156 arg_pos += arg_size(arg_pos, type);
157 }
158 return arg_pos-(uint8_t*)msg;
159}
160
161size_t rtosc_message(char *buffer,
162 size_t len,
163 const char *address,
164 const char *arguments,
165 ...)
166{
167 va_list va;
168 va_start(va, arguments);
169 size_t result = rtosc_vmessage(buffer, len, address, arguments, va);
170 va_end(va);
171 return result;
172}
173
174//Calculate the size of the message without writing to a buffer
175static size_t vsosc_null(const char *address,
176 const char *arguments,
177 const rtosc_arg_t *args)
178{
179 unsigned pos = 0;
180 pos += strlen(address);
181 pos += 4-pos%4;//get 32 bit alignment
182 pos += 1+strlen(arguments);
183 pos += 4-pos%4;
184
185 unsigned toparse = nreserved(arguments);
186 unsigned arg_pos = 0;
187
188 //Take care of varargs
189 while(toparse)
190 {
191 char arg = *arguments++;
192 assert(arg);
193 int i;
194 const char *s;
195 switch(arg) {
196 case 'h':
197 case 't':
198 case 'd':
199 ++arg_pos;
200 pos += 8;
201 --toparse;
202 break;
203 case 'm':
204 case 'r':
205 case 'c':
206 case 'f':
207 case 'i':
208 ++arg_pos;
209 pos += 4;
210 --toparse;
211 break;
212 case 's':
213 case 'S':
214 s = args[arg_pos++].s;
215 assert(s && "Input strings CANNOT be NULL");
216 pos += strlen(s);
217 pos += 4-pos%4;
218 --toparse;
219 break;
220 case 'b':
221 i = args[arg_pos++].b.len;
222 pos += 4 + i;
223 if(pos%4)
224 pos += 4-pos%4;
225 --toparse;
226 break;
227 default:
228 ;
229 }
230 }
231
232 return pos;
233}
234
236
238 size_t lsize, size_t rsize,
239 const rtosc_cmp_options* opt)
240{
241#define mfabs(val) (((val) >= 0) ? (val) : -(val))
242
243 if(!opt)
244 opt = &default_cmp_options;
245 if(lsize != rsize)
246 return 0;
247
248 int rval = 1;
249 for(size_t i = 0; i < lsize && rval; ++i, ++lhs, ++rhs)
250 {
251 if(lhs->type == rhs->type)
252 switch(lhs->type)
253 {
254 case 'i':
255 case 'c':
256 case 'r':
257 rval = lhs->val.i == rhs->val.i;
258 break;
259 case 'I':
260 case 'T':
261 case 'F':
262 case 'N':
263 rval = 1;
264 break;
265 case 'f':
266 rval = (opt->float_tolerance == 0.0)
267 ? lhs->val.f == rhs->val.f
268 : mfabs(lhs->val.f - rhs->val.f) <=
269 (float)opt->float_tolerance;
270 break;
271 case 'd':
272 rval = (opt->float_tolerance == 0.0)
273 ? lhs->val.d == rhs->val.d
274 : mfabs(lhs->val.d - rhs->val.d) <=
275 opt->float_tolerance;
276 break;
277 case 'h':
278 rval = lhs->val.h == rhs->val.h;
279 break;
280 case 't':
281 rval = lhs->val.t == rhs->val.t;
282 break;
283 case 'm':
284 rval = 0 == memcmp(lhs->val.m, rhs->val.m, 4);
285 break;
286 case 's':
287 case 'S':
288 rval = (lhs->val.s == NULL || rhs->val.s == NULL)
289 ? lhs->val.s == rhs->val.s
290 : (0 == strcmp(lhs->val.s, rhs->val.s));
291 break;
292 case 'b':
293 {
294 int32_t lbs = lhs->val.b.len,
295 rbs = rhs->val.b.len;
296 rval = lbs == rbs;
297 if(rval)
298 rval = 0 == memcmp(lhs->val.b.data, rhs->val.b.data, lbs);
299 break;
300 }
301 }
302 else
303 {
304 rval = 0;
305 }
306 }
307 return rval;
308#undef mfabs
309}
310
312 size_t lsize, size_t rsize,
313 const rtosc_cmp_options* opt)
314{
315#define cmp_3way(val1,val2) (((val1) == (val2)) \
316 ? 0 \
317 : (((val1) > (val2)) ? 1 : -1))
318#define mfabs(val) (((val) >= 0) ? (val) : -(val))
319
320 if(!opt)
321 opt = &default_cmp_options;
322
323 size_t rval = 0;
324 size_t min = lsize > rsize ? rsize : lsize;
325 for(size_t i = 0; i < min && !rval; ++i, ++lhs, ++rhs)
326 {
327 if(lhs->type == rhs->type)
328 switch(lhs->type)
329 {
330 case 'i':
331 case 'c':
332 case 'r':
333 rval = cmp_3way(lhs->val.i, rhs->val.i);
334 break;
335 case 'I':
336 case 'T':
337 case 'F':
338 case 'N':
339 rval = 0;
340 break;
341 case 'f':
342 rval = (opt->float_tolerance == 0.0)
343 ? cmp_3way(lhs->val.f, rhs->val.f)
344 : (mfabs(lhs->val.f - rhs->val.f)
345 <= (float)opt->float_tolerance)
346 ? 0
347 : ((lhs->val.f > rhs->val.f) ? 1 : -1);
348 break;
349 case 'd':
350 rval = (opt->float_tolerance == 0.0)
351 ? cmp_3way(lhs->val.d, rhs->val.d)
352 : (mfabs(lhs->val.d - rhs->val.d)
353 <= opt->float_tolerance)
354 ? 0
355 : ((lhs->val.d > rhs->val.d) ? 1 : -1);
356 break;
357 case 'h':
358 rval = cmp_3way(lhs->val.h, rhs->val.h);
359 break;
360 case 't':
361 // immediately is considered lower than everything else
362 // this means if you send two events to a client,
363 // one being "immediately" and one being different, the
364 // immediately-event has the higher priority, event if the
365 // other one is in the past
366 rval = (lhs->val.t == 1)
367 ? (rhs->val.t == 1)
368 ? 0
369 : -1 // lhs has higher priority => lhs < rhs
370 : (rhs->val.t == 1)
371 ? 1
372 : cmp_3way(lhs->val.t, rhs->val.t);
373 break;
374 case 'm':
375 rval = memcmp(lhs->val.m, rhs->val.m, 4);
376 break;
377 case 's':
378 case 'S':
379 rval = (lhs->val.s == NULL || rhs->val.s == NULL)
380 ? cmp_3way(lhs->val.s, rhs->val.s)
381 : strcmp(lhs->val.s, rhs->val.s);
382 break;
383 case 'b':
384 {
385 int32_t lbs = lhs->val.b.len,
386 rbs = rhs->val.b.len;
387 int32_t minlen = (lbs < rbs) ? lbs : rbs;
388 rval = memcmp(lhs->val.b.data, rhs->val.b.data, minlen);
389 if(lbs != rbs && !rval)
390 {
391 // both equal until here
392 // the string that ends here is lexicographically smaller
393 rval = (lbs > rbs)
394 ? lhs->val.b.data[minlen]
395 : -rhs->val.b.data[minlen];
396 }
397 else
398 return rval;
399 break;
400 }
401 }
402 else
403 {
404 rval = (lhs->type > rhs->type) ? 1 : -1;
405 }
406 }
407
408 if(rval == 0 && lsize != rsize)
409 {
410 return (lsize > rsize) ? 1 : -1;
411 }
412 return rval;
413
414#undef mfabs
415#undef cmp_3way
416}
417
418void rtosc_v2args(rtosc_arg_t* args, size_t nargs, const char* arg_str,
419 rtosc_va_list_t* ap)
420{
421 unsigned arg_pos = 0;
422 uint8_t *midi_tmp;
423
424 while(arg_pos < nargs)
425 {
426 switch(*arg_str++) {
427 case 'h':
428 case 't':
429 args[arg_pos++].h = va_arg(ap->a, int64_t);
430 break;
431 case 'd':
432 args[arg_pos++].d = va_arg(ap->a, double);
433 break;
434 case 'c':
435 case 'i':
436 case 'r':
437 args[arg_pos++].i = va_arg(ap->a, int);
438 break;
439 case 'm':
440 midi_tmp = va_arg(ap->a, uint8_t *);
441 args[arg_pos].m[0] = midi_tmp[0];
442 args[arg_pos].m[1] = midi_tmp[1];
443 args[arg_pos].m[2] = midi_tmp[2];
444 args[arg_pos++].m[3] = midi_tmp[3];
445 break;
446 case 'S':
447 case 's':
448 args[arg_pos++].s = va_arg(ap->a, const char *);
449 break;
450 case 'b':
451 args[arg_pos].b.len = va_arg(ap->a, int);
452 args[arg_pos].b.data = va_arg(ap->a, unsigned char *);
453 arg_pos++;
454 break;
455 case 'f':
456 args[arg_pos++].f = va_arg(ap->a, double);
457 break;
458 case 'T':
459 case 'F':
460 case 'N':
461 case 'I':
462 args[arg_pos++].T = arg_str[-1];
463 break;
464 default:
465 ;
466 }
467 }
468}
469
470void rtosc_2args(rtosc_arg_t* args, size_t nargs, const char* arg_str, ...)
471{
473 va_start(va.a, arg_str);
474 rtosc_v2args(args, nargs, arg_str, &va);
475 va_end(va.a);
476}
477
478void rtosc_v2argvals(rtosc_arg_val_t* args, size_t nargs, const char* arg_str, va_list ap)
479{
480 rtosc_va_list_t ap2;
481 va_copy(ap2.a, ap);
482 for(size_t i=0; i<nargs; ++i, ++arg_str, ++args)
483 {
484 args->type = *arg_str;
485 rtosc_v2args(&args->val, 1, arg_str, &ap2);
486 }
487}
488
489void rtosc_2argvals(rtosc_arg_val_t* args, size_t nargs, const char* arg_str, ...)
490{
491 va_list va;
492 va_start(va, arg_str);
493 rtosc_v2argvals(args, nargs, arg_str, va);
494 va_end(va);
495}
496
497size_t rtosc_vmessage(char *buffer,
498 size_t len,
499 const char *address,
500 const char *arguments,
501 va_list ap)
502{
503 const unsigned nargs = nreserved(arguments);
504 if(!nargs)
505 return rtosc_amessage(buffer,len,address,arguments,NULL);
506
507 rtosc_arg_t args[nargs];
508 rtosc_va_list_t ap2;
509 va_copy(ap2.a, ap);
510 rtosc_v2args(args, nargs, arguments, &ap2);
511
512 return rtosc_amessage(buffer,len,address,arguments,args);
513}
514
515size_t rtosc_amessage(char *buffer,
516 size_t len,
517 const char *address,
518 const char *arguments,
519 const rtosc_arg_t *args)
520{
521 const size_t total_len = vsosc_null(address, arguments, args);
522
523 if(!buffer)
524 return total_len;
525
526 //Abort if the message cannot fit
527 if(total_len>len) {
528 memset(buffer, 0, len);
529 return 0;
530 }
531
532 memset(buffer, 0, total_len);
533
534 unsigned pos = 0;
535 while(*address)
536 buffer[pos++] = *address++;
537
538 //get 32 bit alignment
539 pos += 4-pos%4;
540
541 buffer[pos++] = ',';
542
543 const char *arg_str = arguments;
544 while(*arg_str)
545 buffer[pos++] = *arg_str++;
546
547 pos += 4-pos%4;
548
549 unsigned toparse = nreserved(arguments);
550 unsigned arg_pos = 0;
551 while(toparse)
552 {
553 char arg = *arguments++;
554 assert(arg);
555 int32_t i;
556 int64_t d;
557 const uint8_t *m;
558 const char *s;
559 const unsigned char *u;
561 switch(arg) {
562 case 'h':
563 case 't':
564 case 'd':
565 d = args[arg_pos++].t;
566 buffer[pos++] = ((d>>56) & 0xff);
567 buffer[pos++] = ((d>>48) & 0xff);
568 buffer[pos++] = ((d>>40) & 0xff);
569 buffer[pos++] = ((d>>32) & 0xff);
570 buffer[pos++] = ((d>>24) & 0xff);
571 buffer[pos++] = ((d>>16) & 0xff);
572 buffer[pos++] = ((d>>8) & 0xff);
573 buffer[pos++] = (d & 0xff);
574 --toparse;
575 break;
576 case 'r':
577 case 'f':
578 case 'c':
579 case 'i':
580 i = args[arg_pos++].i;
581 buffer[pos++] = ((i>>24) & 0xff);
582 buffer[pos++] = ((i>>16) & 0xff);
583 buffer[pos++] = ((i>>8) & 0xff);
584 buffer[pos++] = (i & 0xff);
585 --toparse;
586 break;
587 case 'm':
588 //TODO verify ordering of spec
589 m = args[arg_pos++].m;
590 buffer[pos++] = m[0];
591 buffer[pos++] = m[1];
592 buffer[pos++] = m[2];
593 buffer[pos++] = m[3];
594 --toparse;
595 break;
596 case 'S':
597 case 's':
598 s = args[arg_pos++].s;
599 while(*s)
600 buffer[pos++] = *s++;
601 pos += 4-pos%4;
602 --toparse;
603 break;
604 case 'b':
605 b = args[arg_pos++].b;
606 i = b.len;
607 buffer[pos++] = ((i>>24) & 0xff);
608 buffer[pos++] = ((i>>16) & 0xff);
609 buffer[pos++] = ((i>>8) & 0xff);
610 buffer[pos++] = (i & 0xff);
611 u = b.data;
612 if(u) {
613 while(i--)
614 buffer[pos++] = *u++;
615 }
616 else
617 pos += i;
618 if(pos%4)
619 pos += 4-pos%4;
620 --toparse;
621 break;
622 default:
623 ;
624 }
625 }
626
627 return pos;
628}
629
630static rtosc_arg_t extract_arg(const uint8_t *arg_pos, char type)
631{
632 rtosc_arg_t result = {0};
633 //trivial case
634 if(!has_reserved(type)) {
635 switch(type)
636 {
637 case 'T':
638 result.T = true;
639 break;
640 case 'F':
641 result.T = false;
642 break;
643 default:
644 ;
645 }
646 } else {
647 switch(type)
648 {
649 case 'h':
650 case 't':
651 case 'd':
652 result.t |= (((uint64_t)*arg_pos++) << 56);
653 result.t |= (((uint64_t)*arg_pos++) << 48);
654 result.t |= (((uint64_t)*arg_pos++) << 40);
655 result.t |= (((uint64_t)*arg_pos++) << 32);
656 result.t |= (((uint64_t)*arg_pos++) << 24);
657 result.t |= (((uint64_t)*arg_pos++) << 16);
658 result.t |= (((uint64_t)*arg_pos++) << 8);
659 result.t |= (((uint64_t)*arg_pos++));
660 break;
661 case 'r':
662 case 'f':
663 case 'c':
664 case 'i':
665 result.i |= (*arg_pos++ << 24);
666 result.i |= (*arg_pos++ << 16);
667 result.i |= (*arg_pos++ << 8);
668 result.i |= (*arg_pos++);
669 break;
670 case 'm':
671 result.m[0] = *arg_pos++;
672 result.m[1] = *arg_pos++;
673 result.m[2] = *arg_pos++;
674 result.m[3] = *arg_pos++;
675 break;
676 case 'b':
677 result.b.len |= (*arg_pos++ << 24);
678 result.b.len |= (*arg_pos++ << 16);
679 result.b.len |= (*arg_pos++ << 8);
680 result.b.len |= (*arg_pos++);
681 result.b.data = (unsigned char *)arg_pos;
682 break;
683 case 'S':
684 case 's':
685 result.s = (char *)arg_pos;
686 break;
687 }
688 }
689
690 return result;
691}
692
693static const char *advance_past_dummy_args(const char *args)
694{
695 while(*args == '[' || *args == ']')
696 args++;
697 return args;
698}
699
701{
702 rtosc_arg_itr_t itr;
704 itr.value_pos = (uint8_t*)(msg+arg_start(msg));
705
706 return itr;
707}
708
710{
711 //current position provides the value
712 rtosc_arg_val_t result = {0,{0}};
713 result.type = *itr->type_pos;
714 if(result.type)
715 result.val = extract_arg(itr->value_pos, result.type);
716
717 //advance
719 char type = result.type;
720 int size = arg_size(itr->value_pos, type);
721 itr->value_pos += size;
722
723
724 return result;
725}
726
728{
729 return !itr.type_pos || !*itr.type_pos;
730}
731
732rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
733{
734 char type = rtosc_type(msg, idx);
735 uint8_t *arg_mem = (uint8_t*)msg + arg_off(msg, idx);
736 return extract_arg(arg_mem, type);
737}
738
739static unsigned char deref(unsigned pos, ring_t *ring)
740{
741 return pos<ring[0].len ? ring[0].data[pos] :
742 ((pos-ring[0].len)<ring[1].len ? ring[1].data[pos-ring[0].len] : 0x00);
743}
744
745static size_t bundle_ring_length(ring_t *ring)
746{
747 unsigned pos = 8+8;//goto first length field
748 uint32_t advance = 0;
749 do {
750 advance = deref(pos+0, ring) << (8*3) |
751 deref(pos+1, ring) << (8*2) |
752 deref(pos+2, ring) << (8*1) |
753 deref(pos+3, ring) << (8*0);
754 if(advance)
755 pos += 4+advance;
756 } while(advance);
757
758 return pos <= (ring[0].len+ring[1].len) ? pos : 0;
759}
760
761//Zero means no full message present
763{
764 //Check if the message is a bundle
765 if(deref(0,ring) == '#' &&
766 deref(1,ring) == 'b' &&
767 deref(2,ring) == 'u' &&
768 deref(3,ring) == 'n' &&
769 deref(4,ring) == 'd' &&
770 deref(5,ring) == 'l' &&
771 deref(6,ring) == 'e' &&
772 deref(7,ring) == '\0')
773 return bundle_ring_length(ring);
774
775 //Proceed for normal messages
776 //Consume path
777 unsigned pos = 0;
778 while(deref(pos++,ring));
779 pos--;
780
781 //Travel through the null word end [1..4] bytes
782 for(int i=0; i<4; ++i)
783 if(deref(++pos, ring))
784 break;
785
786 if(deref(pos, ring) != ',')
787 return 0;
788
789 unsigned aligned_pos = pos;
790 int arguments = pos+1;
791 while(deref(++pos,ring));
792 pos += 4-(pos-aligned_pos)%4;
793
794 unsigned toparse = 0;
795 {
796 int arg = arguments-1;
797 while(deref(++arg,ring))
798 toparse += has_reserved(deref(arg,ring));
799 }
800
801 //Take care of varargs
802 while(toparse)
803 {
804 char arg = deref(arguments++,ring);
805 assert(arg);
806 uint32_t i;
807 switch(arg) {
808 case 'h':
809 case 't':
810 case 'd':
811 pos += 8;
812 --toparse;
813 break;
814 case 'm':
815 case 'r':
816 case 'c':
817 case 'f':
818 case 'i':
819 pos += 4;
820 --toparse;
821 break;
822 case 'S':
823 case 's':
824 while(deref(++pos,ring));
825 pos += 4-(pos-aligned_pos)%4;
826 --toparse;
827 break;
828 case 'b':
829 i = 0;
830 i |= (deref(pos++,ring) << 24);
831 i |= (deref(pos++,ring) << 16);
832 i |= (deref(pos++,ring) << 8);
833 i |= (deref(pos++,ring));
834 pos += i;
835 if((pos-aligned_pos)%4)
836 pos += 4-(pos-aligned_pos)%4;
837 --toparse;
838 break;
839 default:
840 ;
841 }
842 }
843
844
845 return pos <= (ring[0].len+ring[1].len) ? pos : 0;
846}
847
848size_t rtosc_message_length(const char *msg, size_t len)
849{
850 ring_t ring[2] = {{(char*)msg,len},{NULL,0}};
851 return rtosc_message_ring_length(ring);
852}
853
854bool rtosc_valid_message_p(const char *msg, size_t len)
855{
856 //Validate Path Characters (assumes printable characters are sufficient)
857 if(*msg != '/')
858 return false;
859 const char *tmp = msg;
860 for(unsigned i=0; i<len; ++i) {
861 if(*tmp == 0)
862 break;
863 if(!isprint(*tmp))
864 return false;
865 tmp++;
866 }
867
868 //tmp is now either pointing to a null or the end of the string
869 const size_t offset1 = tmp-msg;
870 size_t offset2 = tmp-msg;
871 for(; offset2<len; offset2++) {
872 if(*tmp == ',')
873 break;
874 tmp++;
875 }
876
877 //Too many NULL bytes
878 if(offset2-offset1 > 4)
879 return false;
880
881 if((offset2 % 4) != 0)
882 return false;
883
884 size_t observed_length = rtosc_message_length(msg, len);
885 return observed_length == len;
886}
887static uint64_t extract_uint64(const uint8_t *arg_pos)
888{
889 uint64_t arg = 0;
890 arg |= (((uint64_t)*arg_pos++) << 56);
891 arg |= (((uint64_t)*arg_pos++) << 48);
892 arg |= (((uint64_t)*arg_pos++) << 40);
893 arg |= (((uint64_t)*arg_pos++) << 32);
894 arg |= (((uint64_t)*arg_pos++) << 24);
895 arg |= (((uint64_t)*arg_pos++) << 16);
896 arg |= (((uint64_t)*arg_pos++) << 8);
897 arg |= (((uint64_t)*arg_pos++));
898 return arg;
899}
900
901static uint32_t extract_uint32(const uint8_t *arg_pos)
902{
903 uint32_t arg = 0;
904 arg |= (((uint32_t)*arg_pos++) << 24);
905 arg |= (((uint32_t)*arg_pos++) << 16);
906 arg |= (((uint32_t)*arg_pos++) << 8);
907 arg |= (((uint32_t)*arg_pos++));
908 return arg;
909}
910
911static void emplace_uint64(uint8_t *buffer, uint64_t d)
912{
913 buffer[0] = ((d>>56) & 0xff);
914 buffer[1] = ((d>>48) & 0xff);
915 buffer[2] = ((d>>40) & 0xff);
916 buffer[3] = ((d>>32) & 0xff);
917 buffer[4] = ((d>>24) & 0xff);
918 buffer[5] = ((d>>16) & 0xff);
919 buffer[6] = ((d>>8) & 0xff);
920 buffer[7] = ((d>>0) & 0xff);
921}
922
923static void emplace_uint32(uint8_t *buffer, uint32_t d)
924{
925 buffer[0] = ((d>>24) & 0xff);
926 buffer[1] = ((d>>16) & 0xff);
927 buffer[2] = ((d>>8) & 0xff);
928 buffer[3] = ((d>>0) & 0xff);
929}
930
931size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms, ...)
932{
933 char *_buffer = buffer;
934 memset(buffer, 0, len);
935 strcpy(buffer, "#bundle");
936 buffer += 8;
937 emplace_uint64((uint8_t*)buffer, tt);
938 buffer += 8;
939 va_list va;
940 va_start(va, elms);
941 for(int i=0; i<elms; ++i) {
942 const char *msg = va_arg(va, const char*);
943 //It is assumed that any passed message/bundle is valid
944 size_t size = rtosc_message_length(msg, -1);
945 emplace_uint32((uint8_t*)buffer, size);
946 buffer += 4;
947 memcpy(buffer, msg, size);
948 buffer+=size;
949 }
950 va_end(va);
951
952 return buffer-_buffer;
953}
954
955
956#define POS ((size_t)(((const char *)lengths) - buffer))
957size_t rtosc_bundle_elements(const char *buffer, size_t len)
958{
959 const uint32_t *lengths = (const uint32_t*) (buffer+16);
960 size_t elms = 0;
961 while(POS < len && extract_uint32((const uint8_t*)lengths)) {
962 lengths += extract_uint32((const uint8_t*)lengths)/4+1;
963
964 if(POS > len)
965 break;
966 ++elms;
967 }
968 return elms;
969}
970#undef POS
971
972const char *rtosc_bundle_fetch(const char *buffer, unsigned elm)
973{
974 const uint32_t *lengths = (const uint32_t*) (buffer+16);
975 size_t elm_pos = 0;
976 while(elm_pos!=elm && extract_uint32((const uint8_t*)lengths)) {
977 ++elm_pos;
978 lengths += extract_uint32((const uint8_t*)lengths)/4+1;
979 }
980
981 return (const char*) (elm==elm_pos?lengths+1:NULL);
982}
983
984size_t rtosc_bundle_size(const char *buffer, unsigned elm)
985{
986 const uint32_t *lengths = (const uint32_t*) (buffer+16);
987 size_t elm_pos = 0;
988 size_t last_len = 0;
989 while(elm_pos!=elm && extract_uint32((const uint8_t*)lengths)) {
990 last_len = extract_uint32((const uint8_t*)lengths);
991 ++elm_pos, lengths+=extract_uint32((const uint8_t*)lengths)/4+1;
992 }
993
994 return last_len;
995}
996
997int rtosc_bundle_p(const char *msg)
998{
999 return !strcmp(msg,"#bundle");
1000}
1001
1002uint64_t rtosc_bundle_timetag(const char *msg)
1003{
1004 return extract_uint64((const uint8_t*)msg+8);
1005}
#define NULL
Definition CarlaBridgeFormat.cpp:30
assert(0)
float arg(const fft_t *freqs, off_t x)
Definition OscilGen.cpp:58
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
unsigned * m
Definition inflate.c:1559
unsigned d
Definition inflate.c:940
struct huft * u[BMAX]
Definition inflate.c:1583
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
int int32_t
Definition mid.cpp:97
unsigned int uint32_t
Definition mid.cpp:100
unsigned char uint8_t
Definition mid.cpp:98
const char * msg
Definition missing_descriptor.c:20
#define min(x, y)
Definition os.h:74
size_t rtosc_message_length(const char *msg, size_t len)
Definition rtosc.c:848
size_t rtosc_vmessage(char *buffer, size_t len, const char *address, const char *arguments, va_list ap)
Definition rtosc.c:497
void rtosc_v2args(rtosc_arg_t *args, size_t nargs, const char *arg_str, rtosc_va_list_t *ap)
Definition rtosc.c:418
size_t rtosc_bundle(char *buffer, size_t len, uint64_t tt, int elms,...)
Definition rtosc.c:931
static void emplace_uint64(uint8_t *buffer, uint64_t d)
Definition rtosc.c:911
static unsigned arg_start(const char *msg_)
Definition rtosc.c:81
unsigned rtosc_narguments(const char *msg)
Definition rtosc.c:19
#define mfabs(val)
static unsigned arg_size(const uint8_t *arg_mem, char type)
Definition rtosc.c:95
size_t rtosc_amessage(char *buffer, size_t len, const char *address, const char *arguments, const rtosc_arg_t *args)
Definition rtosc.c:515
size_t rtosc_message_ring_length(ring_t *ring)
Definition rtosc.c:762
const char * rtosc_argument_string(const char *msg)
Definition rtosc.c:11
static const char * advance_past_dummy_args(const char *args)
Definition rtosc.c:693
static rtosc_arg_t extract_arg(const uint8_t *arg_pos, char type)
Definition rtosc.c:630
const char * rtosc_bundle_fetch(const char *buffer, unsigned elm)
Definition rtosc.c:972
size_t rtosc_message(char *buffer, size_t len, const char *address, const char *arguments,...)
Definition rtosc.c:161
size_t rtosc_bundle_size(const char *buffer, unsigned elm)
Definition rtosc.c:984
rtosc_arg_itr_t rtosc_itr_begin(const char *msg)
Definition rtosc.c:700
size_t rtosc_bundle_elements(const char *buffer, size_t len)
Definition rtosc.c:957
#define POS
Definition rtosc.c:956
static uint32_t extract_uint32(const uint8_t *arg_pos)
Definition rtosc.c:901
int rtosc_arg_vals_eq(rtosc_arg_val_t *lhs, rtosc_arg_val_t *rhs, size_t lsize, size_t rsize, const rtosc_cmp_options *opt)
Definition rtosc.c:237
char rtosc_type(const char *msg, unsigned nargument)
Definition rtosc.c:67
static int has_reserved(char type)
Definition rtosc.c:28
void rtosc_v2argvals(rtosc_arg_val_t *args, size_t nargs, const char *arg_str, va_list ap)
Definition rtosc.c:478
static uint64_t extract_uint64(const uint8_t *arg_pos)
Definition rtosc.c:887
int rtosc_itr_end(rtosc_arg_itr_t itr)
Definition rtosc.c:727
int rtosc_arg_vals_cmp(rtosc_arg_val_t *lhs, rtosc_arg_val_t *rhs, size_t lsize, size_t rsize, const rtosc_cmp_options *opt)
Definition rtosc.c:311
rtosc_arg_val_t rtosc_itr_next(rtosc_arg_itr_t *itr)
Definition rtosc.c:709
static unsigned nreserved(const char *args)
Definition rtosc.c:58
uint64_t rtosc_bundle_timetag(const char *msg)
Definition rtosc.c:1002
void rtosc_2argvals(rtosc_arg_val_t *args, size_t nargs, const char *arg_str,...)
Definition rtosc.c:489
static const rtosc_cmp_options default_cmp_options
Definition rtosc.c:235
void rtosc_2args(rtosc_arg_t *args, size_t nargs, const char *arg_str,...)
Definition rtosc.c:470
int rtosc_bundle_p(const char *msg)
Definition rtosc.c:997
rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
Definition rtosc.c:732
static void emplace_uint32(uint8_t *buffer, uint32_t d)
Definition rtosc.c:923
static unsigned arg_off(const char *msg, unsigned idx)
Definition rtosc.c:133
static size_t bundle_ring_length(ring_t *ring)
Definition rtosc.c:745
static unsigned char deref(unsigned pos, ring_t *ring)
Definition rtosc.c:739
bool rtosc_valid_message_p(const char *msg, size_t len)
Definition rtosc.c:854
static size_t vsosc_null(const char *address, const char *arguments, const rtosc_arg_t *args)
Definition rtosc.c:175
#define cmp_3way(val1, val2)
Definition rtosc.h:229
char * data
Definition rtosc.h:230
size_t len
Definition rtosc.h:231
Definition rtosc.h:122
const uint8_t * value_pos
Definition rtosc.h:124
const char * type_pos
Definition rtosc.h:123
Definition rtosc.h:127
rtosc_arg_t val
Definition rtosc.h:129
char type
Definition rtosc.h:128
Definition rtosc.h:41
uint8_t * data
Definition rtosc.h:43
int32_t len
Definition rtosc.h:42
Definition rtosc.h:133
double float_tolerance
< tolerance to when two floats or doubles are equal
Definition rtosc.h:135
va_list container, required for passing va_list as pointers to functions
Definition rtosc.h:166
va_list a
Definition rtosc.h:166
Definition rtosc.h:46
int32_t i
Definition rtosc.h:47
rtosc_blob_t b
Definition rtosc.h:55
float f
Definition rtosc.h:49
char T
Definition rtosc.h:48
uint64_t t
Definition rtosc.h:52
uint8_t m[4]
Definition rtosc.h:53
const char * s
Definition rtosc.h:54
int64_t h
Definition rtosc.h:51
double d
Definition rtosc.h:50
memcpy(hh, h, RAND_HEAD_LEN)
b
Definition crypt.c:628
ulg size
Definition extract.c:2350
int result
Definition process.c:1455