public IEnumerable<string> ScanFile(CASCFile file)
{
if (excludeFileTypes.Contains(Path.GetExtension(file.FullName).ToLower()))
yield break;
Stream fileStream = null;
try
{
fileStream = CASC.OpenFile(file.Hash);
}
catch (Exception exc)
{
Logger.WriteLine("Skipped {0}, error {1}.", file.FullName, exc.Message);
yield break;
}
using (fileStream)
{
int b;
int state = 1;
StringBuilder sb = new StringBuilder();
// look for regex a+(da+)*\.a+ where a = IsAlphaNum() and d = IsFileDelim()
// using a simple state machine
while ((b = fileStream.ReadByte()) > -1)
{
if (state == 1 && IsAlphaNum(b) || state == 2 && IsAlphaNum(b) || state == 3 && IsAlphaNum(b)) // alpha
{
state = 2;
sb.Append((char)b);
if (sb.Length > 10)
{
int nextByte = fileStream.ReadByte();
if (nextByte == 0)
{
string foundStr = sb.ToString();
foreach (var ext in extensions)
yield return foundStr + ext;
}
if (nextByte > -1)
fileStream.Position -= 1;
}
}
else if (state == 2 && IsFileDelim(b)) // delimiter
{
state = 3;
sb.Append((char)b);
}
else if (state == 2 && b == 46) // dot
{
state = 4;
sb.Append((char)b);
}
else if (state == 4 && IsAlphaNum(b)) // extension
{
state = 5;
sb.Append((char)b);
}
else if (state == 5 && IsAlphaNum(b)) // extension
{
sb.Append((char)b);
}
else if (state == 5 && !IsFileChar(b)) // accept
{
state = 1;
if (sb.Length >= 10)
yield return sb.ToString();
sb.Clear();
}
else
{
state = 1;
sb.Clear();
}
}
}
}