Skip to content

Instantly share code, notes, and snippets.

@denisivan0v
Last active April 20, 2018 03:50
Show Gist options
  • Save denisivan0v/90c759ba6fd9192694c1564461c768a0 to your computer and use it in GitHub Desktop.
Save denisivan0v/90c759ba6fd9192694c1564461c768a0 to your computer and use it in GitHub Desktop.
using System;
namespace FilenameMatch
{
internal class Program
{
private static int _testCount = 0;
private static void Main(string[] args)
{
RunTests(
("abc", "abc", true),
("abc", "a", false),
("abc", "ab", false),
("a", "ab", false),
("", "", true),
("", "a", false),
("a", "", false),
("?", "", true),
("*", "", true),
("*a", "", false),
("?a", "", false),
("a*", "", false),
("a?", "", false),
("**", "", true),
("??", "", true),
("*?", "", true),
("?*", "", true),
("*", "abcdef", true),
("**", "abcdef", true),
("*?", "abcdef", true),
("?*", "abcdef", true),
("?*?", "abcdef", true),
("*?*", "abcdef", true),
("a?c", "abc", true),
("a?c", "ac", true),
("a?c", "abbc", false),
("a?c", "bc", false),
("a?c", "bbc", false),
("?a", "a", true),
("?a", "ba", true),
("?a", "cba", false),
("a?", "a", true),
("a?", "ab", true),
("a?", "abc", false),
("a*c", "abc", true),
("a*c", "aac", true),
("a*c", "ac", true),
("a*c", "abbbbbbbbbbbbbbbbbc", true),
("a*c", "abbbbbbbbbbbbbbbbbb", false),
("a*c", "bbbbbbbbbbbbbbbbbbc", false),
("a*c", "ab", false),
("a*c", "bc", false),
("?a?b?c?d?e?", "abcde", true),
("?a?b?c?d?e?", "aabbccddee", true),
("?a?b?c?d?e?", "aaabbbcccdddeee", false),
("*a*b*c*d*e*", "abcde", true),
("*a*b*c*d*e*", "aabbccddee", true),
("*a*b*c*d*e*", "aaabbbcccdddeee", true),
("?a*b*c*d*e", "aaabbbcccdddeee", true),
("?a*b*c*d*e", "aaabbbcccdddeee", true),
("?a*b*c*d*e?", "aaabbbcccdddeee", true),
("?a*b*c*d*e?", "1aaabbbcccdddeee2", true),
("*a?b?c*d*e?", "aabbcccdddeee", true),
("*a?b?c*d*e?", "aaab1bcccdddeee", false),
("*a*b?c*d?e?", "aaabbbcccddee", true),
("*a*b?c*d?e?", "aaabbcccddeeee", false),
("*a*b?c*d?e?", "11aaabbcccdde2", true),
("*a*b?c*d?e*", "aaabbcccddeee", true),
("*a*b?c*d?e???", "aaabbcccddeee", true),
("*.exe", "abcde.exe", true),
("*.exe", "abcde.cmd", false),
("*.ex?", "abcde.exx", true),
("*.ex?", "abcde.ex", true),
("fa*ed?fs*dfa?*ajgf.exe", "faedfsdfaajgf.exe", true),
("fa*ed?fs*dfa?*ajgf.exe", "faedfsdfaajgf.cmd", false),
("fa*ed?fs*dfa?*ajgf.?xe*", "faedfsdfaajgf.xe", true),
("fa*ed?fs*dfa?*ajgf.?xe*", "fa11ed2fs3dfa456ajgf.exe", true),
("fa*ed?fs*dfa?*ajgf.?xe*", "fa11ed2fs3dfa456ajgf.xe", true),
("fa*ed?fs*dfa?*ajgf.?xe*", "fa11ed2fs3dfa456ajgf.xe12345", true),
("fa*ed?fs*dfa?*ajgf.?xe*", "fa11ed2fs3dfa456ajgf.exe12345", true),
("fa*ed?fs*dfa?*ajgf.?xe*", "fa11ed2fs3dfa456ajgf.1exe12345", false));
}
private static void RunTests(params (string pattern, string filename, bool expected)[] values)
{
foreach (var value in values)
{
var result = Matches(value.pattern, value.filename);
Console.Write($"Test #{++_testCount:00}: trying to match '{value.filename}' with '{value.pattern}' -> {result}");
if (value.expected != result)
{
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(" FAIL!");
Console.ForegroundColor = color;
}
Console.Write(Environment.NewLine);
}
}
private static bool Matches(string pattern, string filename)
{
// pattern is empty
if (pattern.Length == 0 && filename.Length > 0)
{
return false;
}
for (var index = 0; index < pattern.Length; index++)
{
var patternCharacter = pattern[index];
// regular symbols
if (patternCharacter != '?' && patternCharacter != '*')
{
// filename is empty, pattern is not empty
if (filename.Length == 0)
{
return false;
}
// end of pattern, but not end of filename
if (index == pattern.Length - 1 && index != filename.Length - 1)
{
return false;
}
// characters doesn't match
if (index < filename.Length && patternCharacter != filename[index])
{
return false;
}
}
var nextCharacterIndex = index + 1;
if (patternCharacter == '?')
{
// end of filename
if (filename.Length == 0)
{
for (var i = nextCharacterIndex; i < pattern.Length; i++)
{
return Matches(pattern.Substring(i), filename);
}
}
// matching 0 or 1 character
if (index < filename.Length)
{
return Matches(pattern.Substring(nextCharacterIndex), filename.Substring(index)) ||
Matches(pattern.Substring(nextCharacterIndex), filename.Substring(nextCharacterIndex));
}
}
if (patternCharacter == '*')
{
// last symbol in pattern
if (index == pattern.Length - 1)
{
return true;
}
// end of filename
if (filename.Length == 0)
{
for (var i = nextCharacterIndex; i < pattern.Length; i++)
{
return Matches(pattern.Substring(i), filename);
}
}
// keep matching
var match = false;
for (var i = index; i < filename.Length; i++)
{
match = match || Matches(pattern.Substring(nextCharacterIndex), filename.Substring(i));
}
return match;
}
}
// both pattern and filename are empty
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment