using System;
namespace ICSharpCode.SharpZipLib.Core
{
#region EventArgs
///
/// Event arguments for scanning.
///
public class ScanEventArgs : EventArgs
{
#region Constructors
///
/// Initialise a new instance of
///
/// The file or directory name.
public ScanEventArgs(string name)
{
name_ = name;
}
#endregion Constructors
///
/// The file or directory name for this event.
///
public string Name
{
get { return name_; }
}
///
/// Get set a value indicating if scanning should continue or not.
///
public bool ContinueRunning
{
get { return continueRunning_; }
set { continueRunning_ = value; }
}
#region Instance Fields
private string name_;
private bool continueRunning_ = true;
#endregion Instance Fields
}
///
/// Event arguments during processing of a single file or directory.
///
public class ProgressEventArgs : EventArgs
{
#region Constructors
///
/// Initialise a new instance of
///
/// The file or directory name if known.
/// The number of bytes processed so far
/// The total number of bytes to process, 0 if not known
public ProgressEventArgs(string name, long processed, long target)
{
name_ = name;
processed_ = processed;
target_ = target;
}
#endregion Constructors
///
/// The name for this event if known.
///
public string Name
{
get { return name_; }
}
///
/// Get set a value indicating whether scanning should continue or not.
///
public bool ContinueRunning
{
get { return continueRunning_; }
set { continueRunning_ = value; }
}
///
/// Get a percentage representing how much of the has been processed
///
/// 0.0 to 100.0 percent; 0 if target is not known.
public float PercentComplete
{
get
{
float result;
if (target_ <= 0)
{
result = 0;
}
else
{
result = ((float)processed_ / (float)target_) * 100.0f;
}
return result;
}
}
///
/// The number of bytes processed so far
///
public long Processed
{
get { return processed_; }
}
///
/// The number of bytes to process.
///
/// Target may be 0 or negative if the value isnt known.
public long Target
{
get { return target_; }
}
#region Instance Fields
private string name_;
private long processed_;
private long target_;
private bool continueRunning_ = true;
#endregion Instance Fields
}
///
/// Event arguments for directories.
///
public class DirectoryEventArgs : ScanEventArgs
{
#region Constructors
///
/// Initialize an instance of .
///
/// The name for this directory.
/// Flag value indicating if any matching files are contained in this directory.
public DirectoryEventArgs(string name, bool hasMatchingFiles)
: base(name)
{
hasMatchingFiles_ = hasMatchingFiles;
}
#endregion Constructors
///
/// Get a value indicating if the directory contains any matching files or not.
///
public bool HasMatchingFiles
{
get { return hasMatchingFiles_; }
}
private readonly
#region Instance Fields
bool hasMatchingFiles_;
#endregion Instance Fields
}
///
/// Arguments passed when scan failures are detected.
///
public class ScanFailureEventArgs : EventArgs
{
#region Constructors
///
/// Initialise a new instance of
///
/// The name to apply.
/// The exception to use.
public ScanFailureEventArgs(string name, Exception e)
{
name_ = name;
exception_ = e;
continueRunning_ = true;
}
#endregion Constructors
///
/// The applicable name.
///
public string Name
{
get { return name_; }
}
///
/// The applicable exception.
///
public Exception Exception
{
get { return exception_; }
}
///
/// Get / set a value indicating whether scanning should continue.
///
public bool ContinueRunning
{
get { return continueRunning_; }
set { continueRunning_ = value; }
}
#region Instance Fields
private string name_;
private Exception exception_;
private bool continueRunning_;
#endregion Instance Fields
}
#endregion EventArgs
#region Delegates
///
/// Delegate invoked before starting to process a file.
///
/// The source of the event
/// The event arguments.
public delegate void ProcessFileHandler(object sender, ScanEventArgs e);
///
/// Delegate invoked during processing of a file or directory
///
/// The source of the event
/// The event arguments.
public delegate void ProgressHandler(object sender, ProgressEventArgs e);
///
/// Delegate invoked when a file has been completely processed.
///
/// The source of the event
/// The event arguments.
public delegate void CompletedFileHandler(object sender, ScanEventArgs e);
///
/// Delegate invoked when a directory failure is detected.
///
/// The source of the event
/// The event arguments.
public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e);
///
/// Delegate invoked when a file failure is detected.
///
/// The source of the event
/// The event arguments.
public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e);
#endregion Delegates
///
/// FileSystemScanner provides facilities scanning of files and directories.
///
public class FileSystemScanner
{
#region Constructors
///
/// Initialise a new instance of
///
/// The file filter to apply when scanning.
public FileSystemScanner(string filter)
{
fileFilter_ = new PathFilter(filter);
}
///
/// Initialise a new instance of
///
/// The file filter to apply.
/// The directory filter to apply.
public FileSystemScanner(string fileFilter, string directoryFilter)
{
fileFilter_ = new PathFilter(fileFilter);
directoryFilter_ = new PathFilter(directoryFilter);
}
///
/// Initialise a new instance of
///
/// The file filter to apply.
public FileSystemScanner(IScanFilter fileFilter)
{
fileFilter_ = fileFilter;
}
///
/// Initialise a new instance of
///
/// The file filter to apply.
/// The directory filter to apply.
public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter)
{
fileFilter_ = fileFilter;
directoryFilter_ = directoryFilter;
}
#endregion Constructors
#region Delegates
///
/// Delegate to invoke when a directory is processed.
///
public event EventHandler ProcessDirectory;
///
/// Delegate to invoke when a file is processed.
///
public ProcessFileHandler ProcessFile;
///
/// Delegate to invoke when processing for a file has finished.
///
public CompletedFileHandler CompletedFile;
///
/// Delegate to invoke when a directory failure is detected.
///
public DirectoryFailureHandler DirectoryFailure;
///
/// Delegate to invoke when a file failure is detected.
///
public FileFailureHandler FileFailure;
#endregion Delegates
///
/// Raise the DirectoryFailure event.
///
/// The directory name.
/// The exception detected.
private bool OnDirectoryFailure(string directory, Exception e)
{
DirectoryFailureHandler handler = DirectoryFailure;
bool result = (handler != null);
if (result)
{
var args = new ScanFailureEventArgs(directory, e);
handler(this, args);
alive_ = args.ContinueRunning;
}
return result;
}
///
/// Raise the FileFailure event.
///
/// The file name.
/// The exception detected.
private bool OnFileFailure(string file, Exception e)
{
FileFailureHandler handler = FileFailure;
bool result = (handler != null);
if (result)
{
var args = new ScanFailureEventArgs(file, e);
FileFailure(this, args);
alive_ = args.ContinueRunning;
}
return result;
}
///
/// Raise the ProcessFile event.
///
/// The file name.
private void OnProcessFile(string file)
{
ProcessFileHandler handler = ProcessFile;
if (handler != null)
{
var args = new ScanEventArgs(file);
handler(this, args);
alive_ = args.ContinueRunning;
}
}
///
/// Raise the complete file event
///
/// The file name
private void OnCompleteFile(string file)
{
CompletedFileHandler handler = CompletedFile;
if (handler != null)
{
var args = new ScanEventArgs(file);
handler(this, args);
alive_ = args.ContinueRunning;
}
}
///
/// Raise the ProcessDirectory event.
///
/// The directory name.
/// Flag indicating if the directory has matching files.
private void OnProcessDirectory(string directory, bool hasMatchingFiles)
{
EventHandler handler = ProcessDirectory;
if (handler != null)
{
var args = new DirectoryEventArgs(directory, hasMatchingFiles);
handler(this, args);
alive_ = args.ContinueRunning;
}
}
///
/// Scan a directory.
///
/// The base directory to scan.
/// True to recurse subdirectories, false to scan a single directory.
public void Scan(string directory, bool recurse)
{
alive_ = true;
ScanDir(directory, recurse);
}
private void ScanDir(string directory, bool recurse)
{
try
{
string[] names = System.IO.Directory.GetFiles(directory);
bool hasMatch = false;
for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex)
{
if (!fileFilter_.IsMatch(names[fileIndex]))
{
names[fileIndex] = null;
}
else
{
hasMatch = true;
}
}
OnProcessDirectory(directory, hasMatch);
if (alive_ && hasMatch)
{
foreach (string fileName in names)
{
try
{
if (fileName != null)
{
OnProcessFile(fileName);
if (!alive_)
{
break;
}
}
}
catch (Exception e)
{
if (!OnFileFailure(fileName, e))
{
throw;
}
}
}
}
}
catch (Exception e)
{
if (!OnDirectoryFailure(directory, e))
{
throw;
}
}
if (alive_ && recurse)
{
try
{
string[] names = System.IO.Directory.GetDirectories(directory);
foreach (string fulldir in names)
{
if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir)))
{
ScanDir(fulldir, true);
if (!alive_)
{
break;
}
}
}
}
catch (Exception e)
{
if (!OnDirectoryFailure(directory, e))
{
throw;
}
}
}
}
#region Instance Fields
///
/// The file filter currently in use.
///
private IScanFilter fileFilter_;
///
/// The directory filter currently in use.
///
private IScanFilter directoryFilter_;
///
/// Flag indicating if scanning should continue running.
///
private bool alive_;
#endregion Instance Fields
}
}