mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
230 lines
4.8 KiB
C++
230 lines
4.8 KiB
C++
/*
|
|
* 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: glob.c,v $
|
|
* 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
|
|
*/
|
|
|
|
#ifndef NEGATE
|
|
#define NEGATE '^' /* std cset negation char */
|
|
#endif
|
|
|
|
bool amatch(const char *str, const char *p)
|
|
{
|
|
int negate;
|
|
int match;
|
|
int c;
|
|
bool np;
|
|
|
|
while (*p) {
|
|
if (!*str && *p != '*' && *p!=':')
|
|
return false;
|
|
|
|
switch (c = *p++) {
|
|
|
|
case ':':
|
|
case '*':
|
|
np=false;
|
|
if( c==':')
|
|
np=true;
|
|
|
|
while (*p == '*' || *p==':')
|
|
p++;
|
|
|
|
if(!np)
|
|
{
|
|
if (!*p)
|
|
return true;
|
|
}
|
|
|
|
if (*p != '?' && *p != '[' && *p != '\\')
|
|
while (*str && (!np || (*str!='/' && *str!='\\') ) && *p != *str)
|
|
str++;
|
|
|
|
if(np)
|
|
{
|
|
if(!*p && !*str)
|
|
return true;
|
|
}
|
|
|
|
while (*str) {
|
|
if (amatch(str, p))
|
|
return true;
|
|
if( np && (*str=='\\' || *str=='/') )
|
|
break;
|
|
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;
|
|
|
|
case '\\':
|
|
if (*p)
|
|
c = *p++;
|
|
default:
|
|
if (c != *str)
|
|
return false;
|
|
break;
|
|
|
|
}
|
|
str++;
|
|
}
|
|
|
|
return !*str;
|
|
}
|
|
|
|
bool test_amatch(void)
|
|
{
|
|
if(amatch("foo bar", "* bar")==false)
|
|
return false;
|
|
|
|
if(amatch("foo\\ bar", "*\\ bar")==false)
|
|
return false;
|
|
|
|
if(amatch("abcdef", "*")==false)
|
|
return false;
|
|
if(amatch("abcdef", ":")==false)
|
|
return false;
|
|
if(amatch("abcdef", "abcdef:")==false)
|
|
return false;
|
|
if(amatch("abcdef", "abcdef:\\\\")==true)
|
|
return false;
|
|
if(amatch("abcdef/", ":")==true)
|
|
return false;
|
|
if(amatch("abcdef/", ":/")==false)
|
|
return false;
|
|
if(amatch("abcdef\\", ":")==true)
|
|
return false;
|
|
if(amatch("abcdef\\", ":\\\\")==false)
|
|
return false;
|
|
|
|
if(amatch("abcdef/asd", ":/asd")==false)
|
|
return false;
|
|
if(amatch("abcdef\\asd", ":asd")==true)
|
|
return false;
|
|
if(amatch("abcdef\\asd", ":\\\\asd")==false)
|
|
return false;
|
|
|
|
if(amatch("abcdef/asd", ":/:")==false)
|
|
return false;
|
|
if(amatch("abcdef\\asd", "::")==true)
|
|
return false;
|
|
if(amatch("abcdef\\asd", ":\\\\:")==false)
|
|
return false;
|
|
if(amatch("abcdef\\", ":\\\\:")==false)
|
|
return false;
|
|
|
|
if(amatch("cvab_abba", "*ab*ab*ba")==false)
|
|
return false;
|
|
if(amatch("cvab_abba", "*abab*ba")==true)
|
|
return false;
|
|
|
|
if(amatch("cvab_abba", ":ab:ab:ba")==false)
|
|
return false;
|
|
if(amatch("cvab_abba", "abab:ba")==true)
|
|
return false;
|
|
|
|
if(amatch("Users/Bernd/Documents", "Users/:/Documents")==false)
|
|
return false;
|
|
if(amatch("Users/Bernd/bla/Documents", "Users/:/Documents")==true)
|
|
return false;
|
|
if(amatch("Users/Bernd/bla/Documents", "Users/*/Documents")==false)
|
|
return false;
|
|
if(amatch("Users/Bernd/Documents", "Users/:/:/Documents")==true)
|
|
return false;
|
|
if(amatch("Users/Bernd/bla/Documents", "Users/:/:/Documents")==false)
|
|
return false;
|
|
if(amatch("Users/Bernd/bla/Documents/xyz", "Users/:/:/Documents/*")==false)
|
|
return false;
|
|
if(amatch("Users/Bernd/bla/Documents2/xyz", "Users/:/:/Documents/*")==true)
|
|
return false;
|
|
|
|
return true;
|
|
} |