modded version CNMAT/OSC https://github.com/CNMAT/OSC

Dependents:   CVtoOSCConverter

Fork of osc-cnmat by Asperius van Hansen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OSCMatch.c Source File

OSCMatch.c

00001 #define OSC_MATCH_ENABLE_2STARS 1
00002 #define OSC_MATCH_ENABLE_NSTARS 1
00003 /*
00004  Written by John MacCallum, The Center for New Music and Audio Technologies,
00005  University of California, Berkeley.  Copyright (c) 2009, The Regents of
00006  the University of California (Regents).
00007  Permission to use, copy, modify, distribute, and distribute modified versions
00008  of this software and its documentation without fee and without a signed
00009  licensing agreement, is hereby granted, provided that the above copyright
00010  notice, this paragraph and the following two paragraphs appear in all copies,
00011  modifications, and distributions.
00012  
00013  IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
00014  SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
00015  OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
00016  BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00017  
00018  REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
00019  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00020  PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
00021  HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
00022  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00023  */
00024 #include <string.h>
00025 #include "OSCMatch.h"
00026 
00027 static int osc_match_star(const char *pattern, const char *address);
00028 static int osc_match_star_r(const char *pattern, const char *address);
00029 static int osc_match_single_char(const char *pattern, const char *address);
00030 static int osc_match_bracket(const char *pattern, const char *address);
00031 static int osc_match_curly_brace(const char *pattern, const char *address);
00032 
00033 int osc_match(const char *pattern, const char *address, int *pattern_offset, int *address_offset)
00034 {
00035     if(!strcmp(pattern, address)){
00036         *pattern_offset = strlen(pattern);
00037         *address_offset = strlen(address);
00038         return OSC_MATCH_ADDRESS_COMPLETE | OSC_MATCH_PATTERN_COMPLETE;
00039     }
00040     
00041     const char *pattern_start;
00042     const char *address_start;
00043     
00044     pattern_start = pattern;
00045     address_start = address;
00046     
00047     *pattern_offset = 0;
00048     *address_offset = 0;
00049     
00050     while(*address != '\0' && *pattern != '\0'){
00051         if(*pattern == '*'){
00052             if(!osc_match_star(pattern, address)){
00053                 return 0;
00054             }
00055             while(*pattern != '/' && *pattern != '\0'){
00056                 pattern++;
00057             }
00058             while(*address != '/' && *address != '\0'){
00059                 address++;
00060             }
00061         }else if(*address == '*'){
00062             while(*pattern != '/' && *pattern != '\0'){
00063                 pattern++;
00064             }
00065             while(*address != '/' && *address != '\0'){
00066                 address++;
00067             }
00068         }else{
00069             int n = 0;
00070             if(!(n = osc_match_single_char(pattern, address))){
00071                 return 0;
00072             }
00073             if(*pattern == '['){
00074                 while(*pattern != ']'){
00075                     pattern++;
00076                 }
00077                 pattern++;
00078                 address++;
00079             }else if(*pattern == '{'){
00080                 while(*pattern != '}'){
00081                     pattern++;
00082                 }
00083                 pattern++;
00084                 address += n;
00085             }else{
00086                 pattern++;
00087                 address++;
00088             }
00089         }
00090     }
00091     
00092     *pattern_offset = pattern - pattern_start;
00093     *address_offset = address - address_start;
00094     
00095     int r = 0;
00096     
00097     if(*address == '\0') {
00098         r |= OSC_MATCH_ADDRESS_COMPLETE;
00099     }
00100     
00101     if(*pattern == '\0') {
00102         r |= OSC_MATCH_PATTERN_COMPLETE;
00103     }
00104     
00105     return r;
00106 }
00107 
00108 static int osc_match_star(const char *pattern, const char *address)
00109 {
00110     const char *address_start = address;
00111     const char *pattern_start = pattern;
00112     int num_stars = 0;
00113     if(*address == '\0') { return 0; }
00114     while(*address != '/' && *address != '\0'){
00115         address++;
00116     }
00117     while(*pattern != '/' && *pattern != '\0'){
00118         if(*pattern == '*'){
00119             num_stars++;
00120         }
00121         pattern++;
00122     }
00123     pattern--;
00124     address--;
00125     switch(num_stars){
00126         case 1:
00127         {
00128             const char *pp = pattern, *aa = address;
00129             while(*pp != '*'){
00130                 if(!(osc_match_single_char(pp, aa))){
00131                     return 0;
00132                 }
00133                 if(*pp == ']' || *pp == '}'){
00134                     while(*pp != '[' && *pp != '{'){
00135                         pp--;
00136                     }
00137                 }
00138                 pp--;
00139                 aa--;
00140             }
00141         }
00142             break;
00143         case 2:
00144 #if (OSC_MATCH_ENABLE_2STARS == 1)
00145         {
00146             const char *pp = pattern, *aa = address;
00147             while(*pp != '*'){
00148                 if(!(osc_match_single_char(pp, aa))){
00149                     return 0;
00150                 }
00151                 if(*pp == ']' || *pp == '}'){
00152                     while(*pp != '[' && *pp != '{'){
00153                         pp--;
00154                     }
00155                 }
00156                 pp--;
00157                 aa--;
00158             }
00159             aa++; // we want to start one character forward to allow the star to match nothing
00160             const char *star2 = pp;
00161             const char *test = aa;
00162             int i = 0;
00163             while(test > address_start){
00164                 pp = star2 - 1;
00165                 aa = test - 1;
00166                 i++;
00167                 while(*pp != '*'){
00168                     if(!osc_match_single_char(pp, aa)){
00169                         break;
00170                     }
00171                     if(*pp == ']' || *pp == '}'){
00172                         while(*pp != '[' && *pp != '{'){
00173                             pp--;
00174                         }
00175                     }
00176                     pp--;
00177                     aa--;
00178                 }
00179                 if(pp == pattern_start){
00180                     return 1;
00181                 }
00182                 test--;
00183             }
00184             return 0;
00185         }
00186             break;
00187 #else
00188             return 0;
00189 #endif
00190         default:
00191 #if (OSC_MATCH_ENABLE_NSTARS == 1)
00192             return osc_match_star_r(pattern_start, address_start);
00193             break;
00194 #else
00195             return 0;
00196 #endif
00197     }
00198     return 1;
00199 }
00200 
00201 #if (OSC_MATCH_ENABLE_NSTARS == 1)
00202 static int osc_match_star_r(const char *pattern, const char *address)
00203 {
00204     if(*address == '/' || *address == '\0'){
00205         if(*pattern == '/' || *pattern == '\0' || (*pattern == '*' && ((*(pattern + 1) == '/') || *(pattern + 1) == '\0'))){
00206             return 1;
00207         }else{
00208             return 0;
00209         }
00210     }
00211     if(*pattern == '*'){
00212         if(osc_match_star_r(pattern + 1, address)){
00213             return 1;
00214         }else{
00215             return osc_match_star_r(pattern, address + 1);
00216         }
00217     }else{
00218         if(!osc_match_single_char(pattern, address)){
00219             return 0;
00220         }
00221         if(*pattern == '[' || *pattern == '{'){
00222             while(*pattern != ']' && *pattern != '}'){
00223                 pattern++;
00224             }
00225         }
00226         return osc_match_star_r(pattern + 1, address + 1);
00227     }
00228 }
00229 #endif
00230 
00231 static int osc_match_single_char(const char *pattern, const char *address)
00232 {
00233     switch(*pattern){
00234         case '[':
00235             return osc_match_bracket(pattern, address);
00236         case ']':
00237             while(*pattern != '['){
00238                 pattern--;
00239             }
00240             return osc_match_bracket(pattern, address);
00241         case '{':
00242             return osc_match_curly_brace(pattern, address);
00243         case '}':
00244             while(*pattern != '{'){
00245                 pattern--;
00246             }
00247             return osc_match_curly_brace(pattern, address);
00248         case '?':
00249             return 1;
00250         default:
00251             if(*pattern == *address){
00252                 return 1;
00253             }else{
00254                 return 0;
00255             }
00256     }
00257     return 0;
00258 }
00259 
00260 static int osc_match_bracket(const char *pattern, const char *address)
00261 {
00262     pattern++;
00263     int val = 1;
00264     if(*pattern == '!'){
00265         pattern++;
00266         val = 0;
00267     }
00268     int matched = !val;
00269     while(*pattern != ']' && *pattern != '\0'){
00270         // the character we're on now is the beginning of a range
00271         if(*(pattern + 1) == '-'){
00272             if(*address >= *pattern && *address <= *(pattern + 2)){
00273                 matched = val;
00274                 break;
00275             }else{
00276                 pattern += 3;
00277             }
00278         }else{
00279             // just test the character
00280             if(*pattern == *address){
00281                 matched = val;
00282                 break;
00283             }
00284             pattern++;
00285         }
00286     }
00287     return matched;
00288 }
00289 
00290 static int osc_match_curly_brace(const char *pattern, const char *address)
00291 {
00292     pattern++;
00293     const char *ptr = pattern;
00294     while(*ptr != '}' && *ptr != '\0' && *ptr != '/'){
00295         while(*ptr != '}' && *ptr != '\0' && *ptr != '/' && *ptr != ','){
00296             ptr++;
00297         }
00298         int n = ptr - pattern;
00299         if(!strncmp(pattern, address, n)){
00300             return n;
00301         }else{
00302             ptr++;
00303             pattern = ptr;
00304         }
00305     }
00306     return 0;
00307 }