LMMS
Loading...
Searching...
No Matches
dispatch.c
Go to the documentation of this file.
1#include <rtosc/rtosc.h>
2#include <ctype.h>
3#include <assert.h>
4#include <string.h>
5#include <strings.h>
6#include <stdlib.h>
7
8
9#include <stdio.h>
10
11static bool rtosc_match_number(const char **pattern, const char **msg)
12{
13 //Verify both hold digits
14 if(!isdigit(**pattern) || !isdigit(**msg))
15 return false;
16
17 //Read in both numeric values
18 unsigned max = atoi(*pattern);
19 unsigned val = atoi(*msg);
20
22 while(isdigit(**pattern))++*pattern;
23 while(isdigit(**msg))++*msg;
24
25 //Match iff msg number is strictly less than pattern
26 return val < max;
27}
28
29// pattern = /previous/{A,B,C,D,E}/after
30// ^
31// message = /previous/C/after
32// ^
33const char *rtosc_match_options(const char *pattern, const char **msg)
34{
35 const char *preserve = *msg;
36 assert(*pattern == '{');
37 pattern++;
38
39retry:
40
41 while(1) {
42 //Check for special characters
43 if(*pattern == ',' || *pattern == '}') {
44 goto advance_until_end;
45 } else if((*pattern == **msg)) { //verbatim compare
46 if(**msg)
47 ++pattern, ++*msg;
48 else
49 goto try_next;
50 } else
51 goto try_next;
52 }
53
54advance_until_end:
55 while(*pattern && *pattern != '}') pattern++;
56 if(*pattern == '}')
57 pattern++;
58 return pattern;
59try_next:
60 *msg = preserve;
61 while(*pattern && *pattern != '}' && *pattern != ',') pattern++;
62 if(*pattern == ',') {
63 pattern++;
64 goto retry;
65 }
66
67 return NULL;
68}
69
70const char *rtosc_match_path(const char *pattern,
71 const char *msg, const char** path_end)
72{
73 if(!path_end)
74 path_end = &msg; // writing *path_end = msg later will have no effect
75 while(1) {
76 //Check for special characters
77 if(*pattern == ':' && !*msg)
78 return *path_end = msg, pattern;
79 else if(*pattern == '{') {
81 if(!pattern)
82 return NULL;
83 } else if(*pattern == '*') {
84 //advance message and pattern to '/' or ':' and '\0'
85 while(*pattern && *pattern != '/' && *pattern != ':')
86 pattern++;
87 if(*pattern == '/' || *pattern == ':')
88 while(*msg && *msg != '/')
89 msg++;
90 } else if(*pattern == '/' && *msg == '/') {
91 ++pattern;
92 ++msg;
93 if(*pattern == '\0' || *pattern == ':')
94 return *path_end = msg, pattern;
95 } else if(*pattern == '#') {
96 ++pattern;
98 return NULL;
99 } else if((*pattern == *msg)) { //verbatim compare
100 if(*msg)
101 ++pattern, ++msg;
102 else
103 return *path_end = msg, pattern;
104 } else
105 return NULL;
106 }
107}
108
109//Match the arg string or fail
110static bool rtosc_match_args(const char *pattern, const char *msg)
111{
112 //match anything if now arg restriction is present (ie the ':')
113 if(*pattern++ != ':')
114 return true;
115
116 const char *arg_str = rtosc_argument_string(msg);
117 bool arg_match = *pattern || *pattern == *arg_str;
118
119 while(*pattern && *pattern != ':')
120 arg_match &= (*pattern++==*arg_str++);
121
122 if(*pattern==':') {
123 if(arg_match && !*arg_str)
124 return true;
125 else
126 return rtosc_match_args(pattern, msg); //retry
127 }
128
129 return arg_match;
130}
131
132bool rtosc_match(const char *pattern,
133 const char *msg, const char** path_end)
134{
135 const char *arg_pattern = rtosc_match_path(pattern, msg, path_end);
136 if(!arg_pattern)
137 return false;
138 else if(*arg_pattern == ':')
139 return rtosc_match_args(arg_pattern, msg);
140 return true;
141}
142
143
144
145/*
146 * Special characters from the specification:
147 * ' ' space 32
148 * # number sign 35
149 * * asterisk 42
150 * , comma 44
151 * / forward slash 47
152 * ? question mark 63
153 * [ open bracket 91
154 * ] close bracket 93
155 * { open curly brace 123
156 * } close curly brace 125
157 */
158
159#if 0
160QUOTE FROM OSC 1.0 SPEC
161
162'?' in the OSC Address Pattern matches any single character
163'*' in the OSC Address Pattern matches any sequence of zero or more characters
164A string of characters in square brackets (e.g., "[string]") in the OSC Address Pattern matches any character in the string.
165Inside square brackets, the minus sign (-) and exclamation point (!) have special meanings:
166 two characters separated by a minus sign indicate the range of characters between the given two
167in ASCII collating sequence. (A minus sign at the end of the string has no special meaning.)
168 An exclamation point at the beginning of a bracketed string negates the sense of the list,
169 meaning that the list matches any character not in the list.
170(An exclamation point anywhere besides the first character after the open bracket has no special meaning.)
171 A comma-separated list of strings enclosed in curly braces (e.g., "{foo,bar}") in the OSC Address Pattern
172 matches any of the strings in the list.
173#endif
174
175
176
177
178//for literal string X
179//for X+?+[] Y
180//for Y+single{} Z
181//for numeric string N
182//assume a is of the form X
183//assume b is a pattern of the form:
184//* (1)
185//Y (2)
186//Y* (3)
187//*X* (4)
188//Z (5)
189//Z* (6)
190//Y#N (7)
191#define RTOSC_MATCH_ALL 1
192#define RTOSC_MATCH_CHAR 2
193#define RTOSC_MATCH_PARTIAL_CHAR 3
194#define RTOSC_MATCH_SUBSTRING 4
195#define RTOSC_MATCH_OPTIONS 5
196#define RTOSC_MATCH_PARTIAL_OPTIONS 6
197#define RTOSC_MATCH_ENUMERATED 7
199{
200 return c<=0x7f && c != ' ' && c != '#' &&
201 c != '/' && c != '{' && c != '}';
202}
203
205{
206 int charwise_only = 1;
207 const char *last_star = strrchr(pattern, '*');
208 const char *pound = strchr(pattern, '#');
209 if(!strcmp("*", pattern))
210 return RTOSC_MATCH_ALL;
211
212 for(const char *p = pattern;*p;++p)
213 charwise_only &= is_charwise(*p);
214 if(charwise_only && !last_star)
215 return RTOSC_MATCH_CHAR;
216 if(pound)
218
219
220 return 2;
221}
222
223static bool rtosc_match_char(const char **path, const char **pattern)
224{
225 //printf("rtosc_match_char('%s','%s')\n", *path, *pattern);
226 if(**path == **pattern && **path) {
227 ++*path;
228 ++*pattern;
229 return true;
230 } else if(**pattern == '?' && *path) {
231 ++*path;
232 ++*pattern;
233 return true;
234 } else if(**pattern == '[') {
235 bool matched = false;
236 bool negation = false;
237 char last_range = '\0';
238 char to_match = **path;
239 ++*pattern;
240 if(**pattern == '!') {
241 negation = true;
242 ++*pattern;
243 }
244 while(**pattern && **pattern != ']') {
245 last_range = **pattern;
246 if(**pattern == to_match) {
247 matched = true;
248 } else if(**pattern == '-') {//range
249 ++*pattern;
250 char range_high = **pattern;
251 if(range_high == ']' || !range_high)
252 break;
253 if(to_match <= range_high && to_match >= last_range)
254 matched = true;
255 }
256 ++*pattern;
257 }
258 if(**pattern == ']')
259 ++*pattern;
260 ++*path;
261 return negation ^ matched;
262 }
263 return false;
264}
265
266bool rtosc_match_partial(const char *a, const char *b)
267{
268 //assume a is of the form X
269 //assume b is a pattern of the form: (1..6)
270 //This is done to avoid backtracking of any kind
271 //This is an OSC serialization library, not a regex
272 //implementation
273
274 char patternbuf[256];
275 (void) patternbuf;
277
278 if(type == RTOSC_MATCH_ALL)
279 return true;
281 while(rtosc_match_char(&a,&b));
282 if(!*a && !*b)
283 return true;
284 else if(*a && *b=='*' && b[1] == '\0')
285 return true;
286 else
287 return false;
288 } else if(type == 4) {
289 //extract substring
290 const char *sub=NULL;
291 return strstr(a,sub);
292 } else if(type == RTOSC_MATCH_OPTIONS || type == 6) {
293 return false;
294 } else if(type == RTOSC_MATCH_ENUMERATED) {
295 while(rtosc_match_char(&a,&b));
296 if(*a && *b=='#' && b[1] != '\0')
297 return atoi(a) < atoi(b+1);
298 return false;
299 } else
300 return 0;
301 assert(false);
302}
303
305{
306 (void) pattern;
307 return 0;
308
309}
310
311int chunk_path(const char *a, int b, const char *c)
312{
313 (void) a;
314 (void) b;
315 (void) c;
316 return 0;
317}
318void advance_path(const char **a)
319{
320 (void) a;
321}
322
323bool rtosc_match_full_path(const char *pattern, const char *message)
324{
325 assert(false && "This API is a WIP");
326 char subpattern[256];
327 char submessage[256];
328 const char *p = pattern;
329 const char *m = message;
330
331step:
332 if(*p != *m)
333 return 0;
334 if(chunk_path(subpattern, sizeof(subpattern), p))
335 return 0;
336 if(chunk_path(submessage, sizeof(submessage), m))
337 return 0;
338
339 advance_path(&p);
340 advance_path(&m);
341
342 if(*p == 0 && *m == 0)
343 return 1;
344 else
345 goto step;
346}
#define NULL
Definition CarlaBridgeFormat.cpp:30
assert(0)
uint8_t a
Definition Spc_Cpu.h:141
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
* e
Definition inflate.c:1404
unsigned * m
Definition inflate.c:1559
int g
Definition inflate.c:1573
bool rtosc_match_partial(const char *a, const char *b)
Definition dispatch.c:266
#define RTOSC_MATCH_ENUMERATED
Definition dispatch.c:197
int rtosc_subpath_pat_type(const char *pattern)
Definition dispatch.c:204
static bool rtosc_match_char(const char **path, const char **pattern)
Definition dispatch.c:223
#define RTOSC_MATCH_OPTIONS
Definition dispatch.c:195
bool rtosc_match_full_path(const char *pattern, const char *message)
Definition dispatch.c:323
const char * rtosc_match_options(const char *pattern, const char **msg)
Definition dispatch.c:33
static bool rtosc_match_number(const char **pattern, const char **msg)
Definition dispatch.c:11
void advance_path(const char **a)
Definition dispatch.c:318
#define RTOSC_MATCH_PARTIAL_CHAR
Definition dispatch.c:193
bool rtosc_match(const char *pattern, const char *msg, const char **path_end)
Definition dispatch.c:132
static bool rtosc_match_args(const char *pattern, const char *msg)
Definition dispatch.c:110
const char * rtosc_match_path(const char *pattern, const char *msg, const char **path_end)
Definition dispatch.c:70
#define RTOSC_MATCH_CHAR
Definition dispatch.c:192
int chunk_path(const char *a, int b, const char *c)
Definition dispatch.c:311
int rtosc_matchable_path(const char *pattern)
Definition dispatch.c:304
static bool is_charwise(uint8_t c)
Definition dispatch.c:198
#define RTOSC_MATCH_ALL
Definition dispatch.c:191
int val
Definition jpeglib.h:956
#define A(x)
Definition lice_arc.cpp:13
float in
Definition lilv_test.c:1460
unsigned char uint8_t
Definition mid.cpp:98
const char * msg
Definition missing_descriptor.c:20
void zero(float &v)
Set a float to zero.
Definition primitives.h:41
constexpr NumericType square(NumericType n) noexcept
Definition juce_MathsFunctions.h:580
#define max(x, y)
Definition os.h:78
bool has(T &t, Z &z)
Definition ports.cpp:334
const char * rtosc_argument_string(const char *msg)
Definition rtosc.c:11
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
b
Definition crypt.c:628
int * pattern
Definition match.c:126
#define void
Definition unzip.h:396