diff options
author | Wayne Davison <wayned@samba.org> | 2006-01-02 17:46:15 +0000 |
---|---|---|
committer | Wayne Davison <wayned@samba.org> | 2006-01-02 17:46:15 +0000 |
commit | 390621a7ab9a58573240fcb926c1c680c51141d5 (patch) | |
tree | 59e53f34001d062b906027f471c5dcbe3be8035f /lib | |
parent | 478bb47c40f7cbf4f766d574e110cb403a369469 (diff) | |
download | android_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.c | 157 |
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; +} |