[Asterisk-Dev] better pattern matcher
Reini Urban
r.urban at inode.at
Tue Jun 10 08:48:54 MST 2003
Reini Urban wrote:
> This is my matcher. Most code is in public domain.
And attached is the patch to pbx.c to be applied to CVS.
>> well, for the beginning I added support to continue to match after a "."
>> to be able to add extensions after the dialed number and not only
>> before. :)
>>
>> e.g "_0N.8500" matches my voicemail extension for all dialed numbers.
>>
>> I'll commit this short patch on Tuesday, because I have to do more
>> testing and the weekend is free.
--
Reini Urban - Entwicklung - http://inode.at
-------------- next part --------------
Index: pbx.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx.c,v
retrieving revision 1.21
diff -u -b -b -u -r1.21 pbx.c
--- pbx.c 22 May 2003 04:38:46 -0000 1.21
+++ pbx.c 10 Jun 2003 16:04:59 -0000
@@ -148,6 +148,7 @@
struct ast_hint *next;
};
+int ast_extension_patmatch(const char *pattern, const char *data);
static int pbx_builtin_prefix(struct ast_channel *, void *);
static int pbx_builtin_suffix(struct ast_channel *, void *);
@@ -558,16 +559,100 @@
}\
}
+/* derived from code by Steffen Offermann 1991 (public domain)
+ http://www.cs.umu.se/~isak/Snippets/xstrcmp.c
+*/
+int ast_extension_patmatch(const char *pattern, const char *data)
+{
+ ast_log(LOG_DEBUG, " >>> %s =~ /%s/\n", data, pattern);
+ switch (toupper(*pattern))
+ {
+ case '\0':
+ ast_log(LOG_DEBUG, " !>>> %s => %s\n", data, !*data ? "OK" : "FAIL");
+ return !*data;
+
+ case ' ':
+ case '-':
+ /* Ignore these characters in the pattern */
+ return *data && ast_extension_patmatch(pattern+1, data);
+
+ case '.' : /* wildcard */
+ if (! *(pattern+1) )
+ return *data;
+ else
+ return ast_extension_patmatch(pattern+1, data) || (*data && ast_extension_patmatch(pattern, data+1));
+
+/*
+ case '?' :
+ return *data && ast_extension_patmatch(pattern+1, data+1);
+*/
+ case 'X':
+ return ((*data >= '0') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
+
+ case 'Z':
+ return ((*data >= '1') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
+
+ case 'N':
+ return ((*data >= '2') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
+
+ case '[':
+ /* Begin Mark Spencer CODE */
+ {
+ int i,border=0;
+ char *where;
+ pattern++;
+ where=strchr(pattern,']');
+ if (where)
+ border=(int)(where-pattern);
+ if (!where || border > strlen(pattern)) {
+ ast_log(LOG_WARNING, "Wrong [%s] pattern usage\n", pattern);
+ return 0;
+ }
+ for (i=0; i<border; i++) {
+ if (i+2<border) {
+ if (*data==pattern[i])
+ return 1;
+ else if (pattern[i+1]=='-') {
+ if (*data >= pattern[i] && *data <= pattern[i+2]) {
+ return ast_extension_patmatch(where+1, data+1);
+ } else {
+ i+=2;
+ continue;
+ }
+ }
+ }
+ }
+ pattern+=border;
+ break;
+ }
+ /* End Mark Spencer CODE */
+
+ default :
+ return (toupper(*pattern) == toupper(*data)) && ast_extension_patmatch(pattern+1, data+1);
+ }
+ return 0;
+}
+
int ast_extension_match(char *pattern, char *data)
{
int match;
- /* If they're the same return */
- if (!strcmp(pattern, data))
- return 1;
- EXTENSION_MATCH_CORE(data,pattern,match);
- /* Must be at the end of both */
- if (*data || (*pattern && (*pattern != '/')))
- match = 0;
+ if (!*pattern) {
+ ast_log(LOG_WARNING, "ast_extension_match: empty pattern\n");
+ return 0;
+ }
+ if (!*data) {
+ ast_log(LOG_WARNING, "ast_extension_match: empty data\n");
+ return 0;
+ }
+ if (pattern[0] != '_') {
+ match = (strcmp(pattern, data) == 0);
+ ast_log(LOG_DEBUG, "ast_extension_match %s == /%s/", data, pattern);
+ return (strcmp(pattern, data) == 0);
+ } else {
+ ast_log(LOG_DEBUG, "ast_extension_match %s =~ /%s/", data, pattern);
+ match = ast_extension_patmatch(data,pattern+1);
+ }
+ ast_log(LOG_DEBUG, " => %d\n", match);
return match;
}
@@ -583,7 +668,9 @@
(!needmore || (strlen(pattern) > strlen(data)))) {
return 1;
}
- EXTENSION_MATCH_CORE(data,pattern,match);
+ if (pattern[0] == '_') {
+ match = ast_extension_patmatch(data,pattern+1);
+ }
/* If there's more or we don't care about more, return non-zero, otlherwise it's a miss */
if (!needmore || *pattern) {
return match;
More information about the asterisk-dev
mailing list