/* Open SoundControl kit in C++ *//* Copyright (C) 2002-2004 libOSC++ contributors. See AUTHORS *//* *//* This library is free software; you can redistribute it and/or *//* modify it under the terms of the GNU Lesser General Public *//* License as published by the Free Software Foundation; either *//* version 2.1 of the License, or (at your option) any later version. *//* *//* This library is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *//* Lesser General Public License for more details. *//* *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *//* For questions regarding this program contact *//* Daniel Holth <dholth@fastmail.fm> or visit *//* http://wiretap.stetson.edu/ *//* In the sprit of the public domain, my modifications to this file are also *//* dedicated to the public domain. Daniel Holth, Oct. 2004 *//* ChangeLog: * * 2004-10-29 Import, convert to C++, begin OSC syntax changes. -dwh * OSC syntax changes are now working, needs more testing. * */// Original header and syntax: /* * robust glob pattern matcher * ozan s. yigit/dec 1994 * public domain * * glob patterns: * * matches zero or more characters * ? matches any single character * [set] matches any character in the set * [^set] matches any character NOT in the set * where a set is a group of characters or ranges. a range * is written as two characters seperated with a hyphen: a-z denotes * all characters between a to z inclusive. * [-set] set matches a literal hypen and any character in the set * []set] matches a literal close bracket and any character in the set * * char matches itself except where char is '*' or '?' or '[' * \char matches char, including any pattern character * * examples: * a*c ac abc abbc ... * a?c acc abc aXc ... * a[a-z]c aac abc acc ... * a[-a-z]c a-c aac abc ... * * $Log$ * Revision 1.1 2004/11/19 23:00:57 theno23 * Added lo_send_timestamped * * Revision 1.3 1995/09/14 23:24:23 oz * removed boring test/main code. * * Revision 1.2 94/12/11 10:38:15 oz * cset code fixed. it is now robust and interprets all * variations of cset [i think] correctly, including [z-a] etc. * * Revision 1.1 94/12/08 12:45:23 oz * Initial revision */#include "lo.h"#ifndef NEGATE#define NEGATE '!'#endif#ifndef true#define true 1#endif#ifndef false#define false 0#endifint lo_pattern_match(const char *str, const char *p){ int negate; int match; char c; while (*p) { if (!*str && *p != '*') return false; switch (c = *p++) { case '*': while (*p == '*' && *p != '/') p++; if (!*p) return true;// if (*p != '?' && *p != '[' && *p != '\\') if (*p != '?' && *p != '[' && *p != '{') while (*str && *p != *str) str++; while (*str) { if (lo_pattern_match(str, p)) return true; str++; } return false; case '?': if (*str) break; return false; /* * set specification is inclusive, that is [a-z] is a, z and * everything in between. this means [z-a] may be interpreted * as a set that contains z, a and nothing in between. */ case '[': if (*p != NEGATE) negate = false; else { negate = true; p++; } match = false; while (!match && (c = *p++)) { if (!*p) return false; if (*p == '-') { /* c-c */ if (!*++p) return false; if (*p != ']') { if (*str == c || *str == *p || (*str > c && *str < *p)) match = true; } else { /* c-] */ if (*str >= c) match = true; break; } } else { /* cc or c] */ if (c == *str) match = true; if (*p != ']') { if (*p == *str) match = true; } else break; } } if (negate == match) return false; /* * if there is a match, skip past the cset and continue on */ while (*p && *p != ']') p++; if (!*p++) /* oops! */ return false; break; /* * {astring,bstring,cstring} */ case '{': { // *p is now first character in the {brace list} const char *place = str; // to backtrack const char *remainder = p; // to forwardtrack // find the end of the brace list while (*remainder && *remainder != '}') remainder++; if (!*remainder++) /* oops! */ return false; c = *p++; while (c) { if (c == ',') { if(lo_pattern_match(str, remainder)) { return true; } else { // backtrack on test string str = place; // continue testing, // skip comma if (!*p++) // oops return false; } } else if (c == '}') { // continue normal pattern matching if (!*p && !*str) return true; str--; // str is incremented again below break; } else if (c == *str) { str++; if (!*str && *remainder) return false; } else { // skip to next comma str = place; while (*p != ',' && *p != '}' && *p) p++; if (*p == ',') p++; else if (*p == '}') { return false; } } c = *p++; } } break; /* Not part of OSC pattern matching case '\\': if (*p) c = *p++; */ default: if (c != *str) return false; break; } str++; } return !*str;}
/* Open SoundControl kit in C++ */
/* Copyright (C) 2002-2004 libOSC++ contributors. See AUTHORS */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */
/* */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* For questions regarding this program contact */
/* Daniel Holth <dholth@fastmail.fm> or visit */
/* http://wiretap.stetson.edu/ */
/* In the sprit of the public domain, my modifications to this file are also */
/* dedicated to the public domain. Daniel Holth, Oct. 2004 */
/* ChangeLog:
*
* 2004-10-29 Import, convert to C++, begin OSC syntax changes. -dwh
* OSC syntax changes are now working, needs more testing.
*
*/
// Original header and syntax:
/*
* robust glob pattern matcher
* ozan s. yigit/dec 1994
* public domain
*
* glob patterns:
* * matches zero or more characters
* ? matches any single character
* [set] matches any character in the set
* [^set] matches any character NOT in the set
* where a set is a group of characters or ranges. a range
* is written as two characters seperated with a hyphen: a-z denotes
* all characters between a to z inclusive.
* [-set] set matches a literal hypen and any character in the set
* []set] matches a literal close bracket and any character in the set
*
* char matches itself except where char is '*' or '?' or '['
* \char matches char, including any pattern character
*
* examples:
* a*c ac abc abbc ...
* a?c acc abc aXc ...
* a[a-z]c aac abc acc ...
* a[-a-z]c a-c aac abc ...
*
* $Log$
* Revision 1.1 2004/11/19 23:00:57 theno23
* Added lo_send_timestamped
*
* Revision 1.3 1995/09/14 23:24:23 oz
* removed boring test/main code.
*
* Revision 1.2 94/12/11 10:38:15 oz
* cset code fixed. it is now robust and interprets all
* variations of cset [i think] correctly, including [z-a] etc.
*
* Revision 1.1 94/12/08 12:45:23 oz
* Initial revision
*/
#include "lo.h"
#ifndef NEGATE
#define NEGATE '!'
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
int lo_pattern_match(const char *str, const char *p)
{
int negate;
int match;
char c;
while (*p) {
if (!*str && *p != '*')
return false;
switch (c = *p++) {
case '*':
while (*p == '*' && *p != '/')
p++;
if (!*p)
return true;
// if (*p != '?' && *p != '[' && *p != '\\')
if (*p != '?' && *p != '[' && *p != '{')
while (*str && *p != *str)
str++;
while (*str) {
if (lo_pattern_match(str, p))
return true;
str++;
}
return false;
case '?':
if (*str)
break;
return false;
/*
* set specification is inclusive, that is [a-z] is a, z and
* everything in between. this means [z-a] may be interpreted
* as a set that contains z, a and nothing in between.
*/
case '[':
if (*p != NEGATE)
negate = false;
else {
negate = true;
p++;
}
match = false;
while (!match && (c = *p++)) {
if (!*p)
return false;
if (*p == '-') { /* c-c */
if (!*++p)
return false;
if (*p != ']') {
if (*str == c || *str == *p ||
(*str > c && *str < *p))
match = true;
}
else { /* c-] */
if (*str >= c)
match = true;
break;
}
}
else { /* cc or c] */
if (c == *str)
match = true;
if (*p != ']') {
if (*p == *str)
match = true;
}
else
break;
}
}
if (negate == match)
return false;
/*
* if there is a match, skip past the cset and continue on
*/
while (*p && *p != ']')
p++;
if (!*p++) /* oops! */
return false;
break;
/*
* {astring,bstring,cstring}
*/
case '{':
{
// *p is now first character in the {brace list}
const char *place = str; // to backtrack
const char *remainder = p; // to forwardtrack
// find the end of the brace list
while (*remainder && *remainder != '}')
remainder++;
if (!*remainder++) /* oops! */
return false;
c = *p++;
while (c) {
if (c == ',') {
if(lo_pattern_match(str, remainder)) {
return true;
} else {
// backtrack on test string
str = place;
// continue testing,
// skip comma
if (!*p++) // oops
return false;
}
}
else if (c == '}') {
// continue normal pattern matching
if (!*p && !*str) return true;
str--; // str is incremented again below
break;
} else if (c == *str) {
str++;
if (!*str && *remainder)
return false;
} else { // skip to next comma
str = place;
while (*p != ',' && *p != '}' && *p)
p++;
if (*p == ',')
p++;
else if (*p == '}') {
return false;
}
}
c = *p++;
}
}
break;
/* Not part of OSC pattern matching
case '\\':
if (*p)
c = *p++;
*/
default:
if (c != *str)
return false;
break;
}
str++;
}
return !*str;
}