diff options
Diffstat (limited to 'liblo/src/pattern_match.c')
-rw-r--r-- | liblo/src/pattern_match.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/liblo/src/pattern_match.c b/liblo/src/pattern_match.c new file mode 100644 index 0000000..fb27091 --- /dev/null +++ b/liblo/src/pattern_match.c @@ -0,0 +1,248 @@ +/* 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/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; +} |