aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2006-01-02 17:46:15 +0000
committerWayne Davison <wayned@samba.org>2006-01-02 17:46:15 +0000
commit390621a7ab9a58573240fcb926c1c680c51141d5 (patch)
tree59e53f34001d062b906027f471c5dcbe3be8035f /lib
parent478bb47c40f7cbf4f766d574e110cb403a369469 (diff)
downloadandroid_external_rsync-390621a7ab9a58573240fcb926c1c680c51141d5.tar.gz
android_external_rsync-390621a7ab9a58573240fcb926c1c680c51141d5.tar.bz2
android_external_rsync-390621a7ab9a58573240fcb926c1c680c51141d5.zip
Added a new function, wildmatch_array(), that lets the caller pass
the text-string as an array of strings (with a terminating NULL pointer at the end). Also added litmatch_array(), which does a literal match (no wildcards or special chars) against an array of strings.
Diffstat (limited to 'lib')
-rw-r--r--lib/wildmatch.c157
1 files changed, 147 insertions, 10 deletions
diff --git a/lib/wildmatch.c b/lib/wildmatch.c
index 2f0023d8..4b54864f 100644
--- a/lib/wildmatch.c
+++ b/lib/wildmatch.c
@@ -59,8 +59,9 @@ int wildmatch_iteration_count;
static int force_lower_case = 0;
-/* Match pattern "p" against string "text". */
-static int dowild(const uchar *p, const uchar *text)
+/* Match pattern "p" against the a virtually-joined string consisting
+ * of "text" and any strings in array "a". */
+static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
{
uchar p_ch;
@@ -71,8 +72,14 @@ static int dowild(const uchar *p, const uchar *text)
for ( ; (p_ch = *p) != '\0'; text++, p++) {
int matched, special;
uchar t_ch, prev_ch;
- if ((t_ch = *text) == '\0' && p_ch != '*')
- return ABORT_ALL;
+ while ((t_ch = *text) == '\0') {
+ if (*a == NULL) {
+ if (p_ch != '*')
+ return ABORT_ALL;
+ break;
+ }
+ text = *a++;
+ }
if (force_lower_case && ISUPPER(t_ch))
t_ch = tolower(t_ch);
switch (p_ch) {
@@ -99,14 +106,27 @@ static int dowild(const uchar *p, const uchar *text)
if (*p == '\0') {
/* Trailing "**" matches everything. Trailing "*" matches
* only if there are no more slash characters. */
- return special? TRUE : strchr((char*)text, '/') == NULL;
+ if (!special) {
+ do {
+ if (strchr((char*)text, '/') != NULL)
+ return FALSE;
+ } while ((text = *a++) != NULL);
+ }
+ return TRUE;
}
- for ( ; t_ch; (t_ch = *++text)) {
- if ((matched = dowild(p, text)) != FALSE) {
+ while (1) {
+ if (t_ch == '\0') {
+ if ((text = *a++) == NULL)
+ break;
+ t_ch = *text;
+ continue;
+ }
+ if ((matched = dowild(p, text, a)) != FALSE) {
if (!special || matched != ABORT_TO_STARSTAR)
return matched;
} else if (!special && t_ch == '/')
return ABORT_TO_STARSTAR;
+ t_ch = *++text;
}
return ABORT_ALL;
case '[':
@@ -205,27 +225,144 @@ static int dowild(const uchar *p, const uchar *text)
}
}
- return *text == '\0';
+ do {
+ if (*text)
+ return FALSE;
+ } while ((text = *a++) != NULL);
+
+ return TRUE;
+}
+
+/* Match literal string "s" against the a virtually-joined string consisting
+ * of "text" and any strings in array "a". */
+static int doliteral(const uchar *s, const uchar *text, const uchar*const *a)
+{
+ for ( ; *s != '\0'; text++, s++) {
+ while (*text == '\0') {
+ if ((text = *a++) == NULL)
+ return FALSE;
+ }
+ if (*text != *s)
+ return FALSE;
+ }
+
+ do {
+ if (*text)
+ return FALSE;
+ } while ((text = *a++) != NULL);
+
+ return TRUE;
+}
+
+/* Return the last "count" path elements from the concatenated string.
+ * We return a string pointer to the start of the string, and update the
+ * array pointer-pointer to point to any remaining string elements. */
+static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
+{
+ const uchar*const *a = *a_ptr;
+ const uchar*const *first_a = a;
+
+ while (*a)
+ a++;
+
+ while (a != first_a) {
+ const uchar *s = *--a;
+ s += strlen((char*)s);
+ while (--s >= *a) {
+ if (*s == '/' && !--count) {
+ *a_ptr = a+1;
+ return s+1;
+ }
+ }
+ }
+
+ if (count == 1) {
+ *a_ptr = a+1;
+ return *a;
+ }
+
+ return NULL;
}
/* Match the "pattern" against the "text" string. */
int wildmatch(const char *pattern, const char *text)
{
+ static const uchar *nomore[1]; /* A NULL pointer. */
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
- return dowild((const uchar*)pattern, (const uchar*)text) == TRUE;
+ return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
}
/* Match the "pattern" against the forced-to-lower-case "text" string. */
int iwildmatch(const char *pattern, const char *text)
{
+ static const uchar *nomore[1]; /* A NULL pointer. */
int ret;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
force_lower_case = 1;
- ret = dowild((const uchar*)pattern, (const uchar*)text) == TRUE;
+ ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
force_lower_case = 0;
return ret;
}
+
+/* Match pattern "p" against the a virtually-joined string consisting
+ * of all the pointers in array "texts" (which has a NULL pointer at the
+ * end). The int "where" can be 0 (normal matching), > 0 (match only
+ * the trailing N slash-separated filename components of "texts"), or < 0
+ * (match the "pattern" at the start or after any slash in "texts"). */
+int wildmatch_array(const char *pattern, const char*const *texts, int where)
+{
+ const uchar *p = (const uchar*)pattern;
+ const uchar*const *a = (const uchar*const*)texts;
+ const uchar *text;
+ int matched;
+
+#ifdef WILD_TEST_ITERATIONS
+ wildmatch_iteration_count = 0;
+#endif
+
+ if (where > 0)
+ text = trailing_N_elements(&a, where);
+ else
+ text = *a++;
+ if (!text)
+ return FALSE;
+
+ if ((matched = dowild(p, text, a)) != TRUE && where < 0
+ && matched != ABORT_ALL) {
+ while (1) {
+ if (*text == '\0') {
+ if ((text = (uchar*)*a++) == NULL)
+ return FALSE;
+ continue;
+ }
+ if (*text++ == '/' && (matched = dowild(p, text, a)) != FALSE
+ && matched != ABORT_TO_STARSTAR)
+ break;
+ }
+ }
+ return matched == TRUE;
+}
+
+/* Match literal string "s" against the a virtually-joined string consisting
+ * of all the pointers in array "texts" (which has a NULL pointer at the
+ * end). The int "where" can be 0 (normal matching), or > 0 (match
+ * only the trailing N slash-separated filename components of "texts"). */
+int litmatch_array(const char *string, const char*const *texts, int where)
+{
+ const uchar *s = (const uchar*)string;
+ const uchar*const *a = (const uchar* const*)texts;
+ const uchar *text;
+
+ if (where > 0)
+ text = trailing_N_elements(&a, where);
+ else
+ text = *a++;
+ if (!text)
+ return FALSE;
+
+ return doliteral(s, text, a) == TRUE;
+}