Skip to content

Commit

Permalink
libwinpr-file: implement recursive pattern matching
Browse files Browse the repository at this point in the history
awakecoding committed Nov 3, 2012
1 parent 1ff1d4c commit cc90fd1
Showing 2 changed files with 102 additions and 24 deletions.
73 changes: 49 additions & 24 deletions winpr/libwinpr/file/file.c
Original file line number Diff line number Diff line change
@@ -328,8 +328,7 @@ LPSTR FilePatternFindNextWildcardA(LPCSTR lpPattern, DWORD* pFlags)
BOOL FilePatternMatchSubExpressionA(LPCSTR lpFileName, size_t cchFileName,
LPCSTR lpX, size_t cchX, LPCSTR lpY, size_t cchY, LPCSTR lpWildcard, LPSTR* ppMatchEnd)
{
printf("FilePatternMatchSubExpressionA: X: %.*s Y: %.*s Wildcard: %.*s FileName: %.*s\n",
cchX, lpX, cchY, lpY, 1, lpWildcard, cchFileName, lpFileName);
LPSTR lpMatch;

if (*lpWildcard == '*')
{
@@ -340,7 +339,9 @@ BOOL FilePatternMatchSubExpressionA(LPCSTR lpFileName, size_t cchFileName,
* X * Y == (0)----->-(1)->-----(2)-----(3)
*/

/* State 0: match 'X' */
/*
* State 0: match 'X'
*/

if (cchFileName < cchX)
return FALSE;
@@ -358,28 +359,62 @@ BOOL FilePatternMatchSubExpressionA(LPCSTR lpFileName, size_t cchFileName,
* State 2: match Y
*/

if (cchFileName < (cchX + cchY))
/* TODO: case insensitive character search */
lpMatch = strchr(&lpFileName[cchX], *lpY);

if (!lpMatch)
return FALSE;

if (_strnicmp(&lpFileName[cchFileName - cchY], lpY, cchY) != 0)
if (_strnicmp(lpMatch, lpY, cchY) != 0)
return FALSE;

/**
* State 3: final state
*/

*ppMatchEnd = (LPSTR) &lpFileName[cchFileName];
*ppMatchEnd = (LPSTR) &lpMatch[cchY];

return TRUE;
}
else if (*lpWildcard == '?')
{
/**
* X S S Y
* X ?? Y == (0)---(1)---(2)---(3)---(4)
* X S Y
* X ? Y == (0)---(1)---(2)---(3)
*/

/*
* State 0: match 'X'
*/

if (cchFileName < cchX)
return FALSE;

if (_strnicmp(lpFileName, lpX, cchX) != 0)
return FALSE;

/*
* State 1: match 'S'
*/

/**
* State 2: match Y
*/

/* TODO: case insensitive character search */
lpMatch = strchr(&lpFileName[cchX + 1], *lpY);

if (!lpMatch)
return FALSE;

if (_strnicmp(lpMatch, lpY, cchY) != 0)
return FALSE;

/**
* State 3: final state
*/

printf("warning: unimplemented '?' pattern match\n");
*ppMatchEnd = (LPSTR) &lpMatch[cchY];

return TRUE;
}
@@ -505,6 +540,10 @@ BOOL FilePatternMatchA(LPCSTR lpFileName, LPCSTR lpPattern)

if (lpWildcard)
{
LPSTR lpX;
LPSTR lpY;
size_t cchX;
size_t cchY;
LPSTR lpMatchEnd;
LPSTR lpSubPattern;
size_t cchSubPattern;
@@ -524,11 +563,6 @@ BOOL FilePatternMatchA(LPCSTR lpFileName, LPCSTR lpPattern)

if (!lpNextWildcard)
{
LPSTR lpX;
LPSTR lpY;
size_t cchX;
size_t cchY;

lpX = (LPSTR) lpSubPattern;
cchX = (lpWildcard - lpSubPattern);

@@ -542,13 +576,9 @@ BOOL FilePatternMatchA(LPCSTR lpFileName, LPCSTR lpPattern)
}
else
{
LPSTR lpX;
LPSTR lpY;
size_t cchX;
size_t cchY;

while (lpNextWildcard)
{
cchSubFileName = cchFileName - (lpSubFileName - lpFileName);
cchNextWildcard = ((dwNextFlags & WILDCARD_DOS) ? 2 : 1);

lpX = (LPSTR) lpSubPattern;
@@ -557,18 +587,13 @@ BOOL FilePatternMatchA(LPCSTR lpFileName, LPCSTR lpPattern)
lpY = (LPSTR) &lpSubPattern[cchX + cchWildcard];
cchY = (lpNextWildcard - lpWildcard) - cchWildcard;

cchSubFileName = (lpNextWildcard - lpSubFileName);

match = FilePatternMatchSubExpressionA(lpSubFileName, cchSubFileName,
lpX, cchX, lpY, cchY, lpWildcard, &lpMatchEnd);

if (!match)
return FALSE;

/* Recursively match subexpressions */

lpSubFileName = lpMatchEnd;
cchSubFileName = strlen(lpSubFileName);

cchWildcard = cchNextWildcard;
lpWildcard = lpNextWildcard;
53 changes: 53 additions & 0 deletions winpr/libwinpr/file/test/TestFilePatternMatch.c
Original file line number Diff line number Diff line change
@@ -100,6 +100,59 @@ int TestFilePatternMatch(int argc, char* argv[])
return -1;
}

/* 'X ? Y' expression */

if (!FilePatternMatchA("X1Y.txt", "X?Y.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X1Y.txt", "X?Y.txt");
return -1;
}

if (FilePatternMatchA("XY.txt", "X?Y.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XY.txt", "X?Y.txt");
return -1;
}

if (FilePatternMatchA("XZ.txt", "X?Y.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XZ.txt", "X?Y.txt");
return -1;
}

if (FilePatternMatchA("X123Z.txt", "X?Y.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Z.txt", "X?Y.txt");
return -1;
}

/* 'X ? Y ? Z' expression */

if (!FilePatternMatchA("X123Y456Z.txt", "X?Y?Z.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456Z.txt", "X?Y?Z.txt");
return -1;
}

if (FilePatternMatchA("XYZ.txt", "X?Y?Z.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYZ.txt", "X?Y?Z.txt");
return -1;
}

if (!FilePatternMatchA("X123Y456W.txt", "X?Y?Z.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456W.txt", "X?Y?Z.txt");
return -1;
}

if (FilePatternMatchA("XYW.txt", "X?Y?Z.txt"))
{
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYW.txt", "X?Y?Z.txt");
return -1;
}


return 0;
}

0 comments on commit cc90fd1

Please sign in to comment.