00001 /********************************************************************************* 00002 00003 Copyright 2006-2008 MakingThings 00004 00005 Licensed under the Apache License, 00006 Version 2.0 (the "License"); you may not use this file except in compliance 00007 with the License. You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software distributed 00012 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00013 CONDITIONS OF ANY KIND, either express or implied. See the License for 00014 the specific language governing permissions and limitations under the License. 00015 00016 *********************************************************************************/ 00017 00018 /* 00019 osc_patternmatch.c 00020 00021 Adapted from OSC-pattern-match.c, by Matt Wright 00022 Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury 00023 */ 00024 00025 #include "config.h" 00026 #ifdef OSC 00027 00028 #include "types.h" 00029 #include "osc.h" 00030 00031 static const char *theWholePattern; /* Just for warning messages */ 00032 00033 static bool MatchBrackets (const char *pattern, const char *test); 00034 static bool MatchList (const char *pattern, const char *test); 00035 00036 bool Osc_PatternMatch(const char * pattern, const char * test) 00037 { 00038 theWholePattern = pattern; 00039 00040 if (pattern == 0 || pattern[0] == 0) 00041 { 00042 return test[0] == 0; 00043 } 00044 00045 if (test[0] == 0) 00046 { 00047 if (pattern[0] == '*') 00048 return Osc_PatternMatch(pattern+1,test); 00049 else 00050 return false; 00051 } 00052 00053 switch (pattern[0]) 00054 { 00055 case 0: 00056 return test[0] == 0; 00057 case '?': 00058 return Osc_PatternMatch(pattern + 1, test + 1); 00059 case '*': 00060 if (Osc_PatternMatch(pattern+1, test)) 00061 return true; 00062 else 00063 return Osc_PatternMatch(pattern, test+1); 00064 case ']': 00065 case '}': 00066 // OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern); 00067 return false; 00068 case '[': 00069 return MatchBrackets (pattern,test); 00070 case '{': 00071 return MatchList (pattern,test); 00072 case '\\': 00073 if (pattern[1] == 0) 00074 return test[0] == 0; 00075 else 00076 { 00077 if (pattern[1] == test[0]) 00078 return Osc_PatternMatch(pattern+2,test+1); 00079 else 00080 return false; 00081 } 00082 default: 00083 if (pattern[0] == test[0]) 00084 return Osc_PatternMatch(pattern+1,test+1); 00085 else 00086 return false; 00087 } 00088 } 00089 00090 00091 /* we know that pattern[0] == '[' and test[0] != 0 */ 00092 00093 static bool MatchBrackets (const char *pattern, const char *test) 00094 { 00095 bool result; 00096 bool negated = false; 00097 const char *p = pattern; 00098 00099 if (pattern[1] == 0) 00100 { 00101 // OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); 00102 return false; 00103 } 00104 00105 if (pattern[1] == '!') 00106 { 00107 negated = true; 00108 p++; 00109 } 00110 00111 while (*p != ']') 00112 { 00113 if (*p == 0) 00114 { 00115 //OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); 00116 return false; 00117 } 00118 if (p[1] == '-' && p[2] != 0) 00119 { 00120 if (test[0] >= p[0] && test[0] <= p[2]) 00121 { 00122 result = !negated; 00123 goto advance; 00124 } 00125 } 00126 if (p[0] == test[0]) 00127 { 00128 result = !negated; 00129 goto advance; 00130 } 00131 p++; 00132 } 00133 00134 result = negated; 00135 00136 advance: 00137 00138 if (!result) 00139 return false; 00140 00141 while (*p != ']') 00142 { 00143 if (*p == 0) 00144 { 00145 //OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); 00146 return false; 00147 } 00148 p++; 00149 } 00150 00151 return Osc_PatternMatch(p+1,test+1); 00152 } 00153 00154 static bool MatchList (const char *pattern, const char *test) 00155 { 00156 00157 const char *restOfPattern, *tp = test; 00158 00159 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) 00160 { 00161 if (*restOfPattern == 0) 00162 { 00163 //OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern); 00164 return false; 00165 } 00166 } 00167 00168 restOfPattern++; /* skip close curly brace */ 00169 00170 pattern++; /* skip open curly brace */ 00171 00172 while (1) 00173 { 00174 if (*pattern == ',') 00175 { 00176 if (Osc_PatternMatch(restOfPattern, tp)) 00177 return true; 00178 else 00179 { 00180 tp = test; 00181 ++pattern; 00182 } 00183 } 00184 else 00185 { 00186 if (*pattern == '}') 00187 return Osc_PatternMatch(restOfPattern, tp); 00188 else 00189 { 00190 if (*pattern == *tp) 00191 { 00192 ++pattern; 00193 ++tp; 00194 } 00195 else 00196 { 00197 tp = test; 00198 while (*pattern != ',' && *pattern != '}') { 00199 pattern++; 00200 } 00201 if (*pattern == ',') 00202 pattern++; 00203 } 00204 } 00205 } 00206 } 00207 } 00208 00209 #endif // OSC 00210 00211 00212
The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.