dovecot-2.0: Added wildcard_match*() for matching strings with '...

dovecot at dovecot.org dovecot at dovecot.org
Thu Mar 18 04:12:27 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/f7d14405de09
changeset: 10941:f7d14405de09
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Mar 18 04:11:55 2010 +0200
description:
Added wildcard_match*() for matching strings with '*' and '?' wildcards.

diffstat:

 src/lib/Makefile.am      |    2 +
 src/lib/wildcard-match.c |  103 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/wildcard-match.h |    9 ++++
 3 files changed, 114 insertions(+), 0 deletions(-)

diffs (139 lines):

diff -r 480bf5fefcce -r f7d14405de09 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Thu Mar 18 04:00:17 2010 +0200
+++ b/src/lib/Makefile.am	Thu Mar 18 04:11:55 2010 +0200
@@ -111,6 +111,7 @@
 	utc-offset.c \
 	utc-mktime.c \
 	var-expand.c \
+	wildcard-match.c \
 	write-full.c
 
 headers = \
@@ -203,6 +204,7 @@
 	utc-offset.h \
 	utc-mktime.h \
 	var-expand.h \
+	wildcard-match.h \
 	write-full.h
 
 test_programs = test-lib
diff -r 480bf5fefcce -r f7d14405de09 src/lib/wildcard-match.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/wildcard-match.c	Thu Mar 18 04:11:55 2010 +0200
@@ -0,0 +1,103 @@
+/*
+ * This code would not have been possible without the prior work and
+ * suggestions of various sourced.  Special thanks to Robey for
+ * all his time/help tracking down bugs and his ever-helpful advice.
+ *
+ * 04/09:  Fixed the "*\*" against "*a" bug (caused an endless loop)
+ *
+ *   Chris Fuller  (aka Fred1 at IRC & Fwitz at IRC)
+ *     crf at cfox.bchs.uh.edu
+ *
+ * I hereby release this code into the public domain
+ *
+ */
+
+#include "lib.h"
+#include "wildcard-match.h"
+
+#include <ctype.h>
+
+#define WILDS '*'  /* matches 0 or more characters (including spaces) */
+#define WILDQ '?'  /* matches ecactly one character */
+
+#define NOMATCH 0
+#define MATCH (match+sofar)
+
+static int wildcard_match_int(const char *data, const char *mask, int icase)
+{
+  const char *ma = mask, *na = data, *lsm = 0, *lsn = 0;
+  int match = 1;
+  int sofar = 0;
+
+  /* null strings should never match */
+  if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
+    return NOMATCH;
+  /* find the end of each string */
+  while (*(++mask));
+  mask--;
+  while (*(++data));
+  data--;
+
+  while (data >= na) {
+    /* If the mask runs out of chars before the string, fall back on
+     * a wildcard or fail. */
+    if (mask < ma) {
+      if (lsm) {
+        data = --lsn;
+        mask = lsm;
+        if (data < na)
+          lsm = 0;
+        sofar = 0;
+      }
+      else
+        return NOMATCH;
+    }
+
+    switch (*mask) {
+    case WILDS:                /* Matches anything */
+      do
+        mask--;                    /* Zap redundant wilds */
+      while ((mask >= ma) && (*mask == WILDS));
+      lsm = mask;
+      lsn = data;
+      match += sofar;
+      sofar = 0;                /* Update fallback pos */
+      if (mask < ma)
+        return MATCH;
+      continue;                 /* Next char, please */
+    case WILDQ:
+      mask--;
+      data--;
+      continue;                 /* '?' always matches */
+    }
+    if (icase ? (i_toupper(*mask) == i_toupper(*data)) :
+	(*mask == *data)) {     /* If matching char */
+      mask--;
+      data--;
+      sofar++;                  /* Tally the match */
+      continue;                 /* Next char, please */
+    }
+    if (lsm) {                  /* To to fallback on '*' */
+      data = --lsn;
+      mask = lsm;
+      if (data < na)
+        lsm = 0;                /* Rewind to saved pos */
+      sofar = 0;
+      continue;                 /* Next char, please */
+    }
+    return NOMATCH;             /* No fallback=No match */
+  }
+  while ((mask >= ma) && (*mask == WILDS))
+    mask--;                        /* Zap leftover %s & *s */
+  return (mask >= ma) ? NOMATCH : MATCH;   /* Start of both = match */
+}
+
+bool wildcard_match(const char *data, const char *mask)
+{
+	return wildcard_match_int(data, mask, FALSE) != 0;
+}
+
+bool wildcard_match_icase(const char *data, const char *mask)
+{
+	return wildcard_match_int(data, mask, TRUE) != 0;
+}
diff -r 480bf5fefcce -r f7d14405de09 src/lib/wildcard-match.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/wildcard-match.h	Thu Mar 18 04:11:55 2010 +0200
@@ -0,0 +1,9 @@
+#ifndef WILDCARD_MATCH_H
+#define WILDCARD_MATCH_H
+
+/* Returns TRUE if mask matches data. mask can contain '*' and '?' wildcards. */
+bool wildcard_match(const char *data, const char *mask);
+/* Like wildcard_match(), but match ASCII characters case-insensitively. */
+bool wildcard_match_icase(const char *data, const char *mask);
+
+#endif


More information about the dovecot-cvs mailing list