mirror of
https://github.com/chylex/Code-Statistics.git
synced 2024-09-12 12:42:47 +02:00
143 lines
4.7 KiB
C#
143 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using FileIO = System.IO.File;
|
|
using DirectoryIO = System.IO.Directory;
|
|
using CodeStatistics.Forms.Project;
|
|
using CodeStatisticsCore.Input;
|
|
|
|
namespace CodeStatistics.Input{
|
|
class FileSearch : IInputMethod{
|
|
public delegate void RefreshEventHandler(int entriesFound);
|
|
public delegate void FinishEventHandler(FileSearchData searchData);
|
|
public delegate void FailureEventHandler(Exception ex);
|
|
|
|
public event RefreshEventHandler Refresh;
|
|
public event FinishEventHandler Finish;
|
|
public event FailureEventHandler Failure;
|
|
private event Action CancelFinish;
|
|
|
|
private readonly string[] rootFiles;
|
|
private readonly CancellationTokenSource cancelToken;
|
|
|
|
public FileSearch(string[] files){
|
|
this.rootFiles = files;
|
|
cancelToken = new CancellationTokenSource();
|
|
}
|
|
|
|
public void StartAsync(){
|
|
var task = new Task(() => {
|
|
var searchData = new FileSearchData(rootFiles.Length == 0 ? string.Empty : IOUtils.FindRootPath(rootFiles));
|
|
var rand = new Random();
|
|
|
|
int[] entryCount = { 0 };
|
|
int nextNotice = 0;
|
|
|
|
Action updateNotice = () => {
|
|
if (--nextNotice < 0){
|
|
if (Refresh != null){
|
|
Refresh(entryCount[0]);
|
|
}
|
|
|
|
nextNotice = 100+rand.Next(50);
|
|
}
|
|
};
|
|
|
|
updateNotice();
|
|
|
|
foreach(string rootFile in rootFiles){
|
|
if (cancelToken.IsCancellationRequested){
|
|
if (CancelFinish != null){
|
|
CancelFinish();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
bool? isDirectory = IOUtils.IsDirectory(rootFile);
|
|
if (!isDirectory.HasValue)continue;
|
|
|
|
if (isDirectory.Value){
|
|
foreach(IOEntry entry in EnumerateEntriesSafe(rootFile)){
|
|
if (cancelToken.IsCancellationRequested){
|
|
if (CancelFinish != null){
|
|
CancelFinish();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
searchData.Add(entry);
|
|
++entryCount[0];
|
|
updateNotice();
|
|
}
|
|
}
|
|
else{
|
|
searchData.Add(new IOEntry(IOEntry.Type.File, rootFile));
|
|
++entryCount[0];
|
|
updateNotice();
|
|
}
|
|
}
|
|
|
|
if (Refresh != null){
|
|
Refresh(entryCount[0]);
|
|
}
|
|
|
|
if (Finish != null){
|
|
Finish(searchData);
|
|
}
|
|
}, cancelToken.Token);
|
|
|
|
task.ContinueWith(originalTask => {
|
|
if (Failure != null){
|
|
Failure(originalTask.Exception);
|
|
}
|
|
}, TaskContinuationOptions.OnlyOnFaulted);
|
|
|
|
task.Start();
|
|
}
|
|
|
|
private static IEnumerable<IOEntry> EnumerateEntriesSafe(string path){
|
|
var foldersLeft = new Queue<string>(64);
|
|
foldersLeft.Enqueue(path);
|
|
|
|
while(foldersLeft.Count > 0){
|
|
string currentFolder = foldersLeft.Dequeue();
|
|
string[] files, folders;
|
|
|
|
try{
|
|
files = DirectoryIO.GetFiles(currentFolder, "*.*", SearchOption.TopDirectoryOnly);
|
|
}catch(Exception){
|
|
files = new string[0];
|
|
}
|
|
|
|
try{
|
|
folders = DirectoryIO.GetDirectories(currentFolder, "*.*", SearchOption.TopDirectoryOnly);
|
|
}catch(Exception){
|
|
folders = new string[0];
|
|
}
|
|
|
|
foreach(string file in files){
|
|
yield return new IOEntry(IOEntry.Type.File, file);
|
|
}
|
|
|
|
foreach(string folder in folders){
|
|
foldersLeft.Enqueue(folder);
|
|
yield return new IOEntry(IOEntry.Type.Folder, folder);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void BeginProcess(ProjectLoadForm.UpdateCallbacks callbacks){
|
|
callbacks.OnReady(this);
|
|
}
|
|
|
|
public void CancelProcess(Action onCancelFinish){
|
|
cancelToken.Cancel(false);
|
|
CancelFinish += onCancelFinish;
|
|
}
|
|
}
|
|
}
|