Real Time Open Sound Control librtosc
 All Classes Namespaces Files Functions Variables Typedefs Macros Pages
matcher.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Mark McCurry
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef RTOSC_MATCH
26 #define RTOSC_MATCH
27 
28 #include <stdbool.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 
32 static bool rtosc_match_number(const char **pattern, const char **msg)
33 {
34  //Verify both hold digits
35  if(!isdigit(**pattern) || !isdigit(**msg))
36  return false;
37 
38  //Read in both numeric values
39  unsigned max = atoi(*pattern);
40  unsigned val = atoi(*msg);
41 
43  while(isdigit(**pattern))++*pattern;
44  while(isdigit(**msg))++*msg;
45 
46  //Match iff msg number is strictly less than pattern
47  return val < max;
48 }
49 static const char *rtosc_match_path(const char *pattern, const char *msg)
50 {
51  while(1) {
52  //Check for special characters
53  if(*pattern == ':')
54  return pattern;
55  else if(*pattern == '/' && *msg == '/')
56  return ++pattern;
57  else if(*pattern == '#') {
58  ++pattern;
59  if(!rtosc_match_number(&pattern, &msg))
60  return NULL;
61  } else if((*pattern == *msg)) { //verbatim compare
62  if(*msg)
63  ++pattern, ++msg;
64  else
65  return pattern;
66  } else
67  return NULL;
68  }
69 }
70 
71 //Match the arg string or fail
72 static bool rtosc_match_args(const char *pattern, const char *msg)
73 {
74  //match anything if now arg restriction is present (ie the ':')
75  if(*pattern++ != ':')
76  return true;
77 
78  const char *arg_str = rtosc_argument_string(msg);
79  bool arg_match = *pattern || *pattern == *arg_str;
80 
81  while(*pattern && *pattern != ':')
82  arg_match &= (*pattern++==*arg_str++);
83 
84  if(*pattern==':') {
85  if(arg_match && !*arg_str)
86  return true;
87  else
88  return rtosc_match_args(pattern, msg); //retry
89  }
90 
91  return arg_match;
92 }
93 
104 static bool rtosc_match(const char *pattern, const char *msg)
105 {
106  const char *arg_pattern = rtosc_match_path(pattern, msg);
107  if(!arg_pattern)
108  return false;
109  else if(*arg_pattern == ':')
110  return rtosc_match_args(arg_pattern, msg);
111  return true;
112 }
113 #endif