summaryrefslogtreecommitdiff
path: root/liblo/src/pattern_match.c
diff options
context:
space:
mode:
Diffstat (limited to 'liblo/src/pattern_match.c')
-rw-r--r--liblo/src/pattern_match.c248
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;
+}