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
///
/// 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
string name_;
bool continueRunning_ = true;
#endregion
}
///
/// 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
///
/// The name for this event if known.
///
public string Name {
get { return name_; }
}
///
/// Get set a value indicating wether 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
string name_;
long processed_;
long target_;
bool continueRunning_ = true;
#endregion
}
///
/// 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
///
/// Get a value indicating if the directory contains any matching files or not.
///
public bool HasMatchingFiles {
get { return hasMatchingFiles_; }
}
readonly
#region Instance Fields
bool hasMatchingFiles_;
#endregion
}
///
/// 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
///
/// The applicable name.
///
public string Name {
get { return name_; }
}
///
/// The applicable exception.
///
public Exception Exception {
get { return exception_; }
}
///
/// Get / set a value indicating wether scanning should continue.
///
public bool ContinueRunning {
get { return continueRunning_; }
set { continueRunning_ = value; }
}
#region Instance Fields
string name_;
Exception exception_;
bool continueRunning_;
#endregion
}
#endregion
#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
///
/// 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
#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
///
/// Raise the DirectoryFailure event.
///
/// The directory name.
/// The exception detected.
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.
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.
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
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.
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);
}
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.
///
IScanFilter fileFilter_;
///
/// The directory filter currently in use.
///
IScanFilter directoryFilter_;
///
/// Flag indicating if scanning should continue running.
///
bool alive_;
#endregion
}
}