using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tools.DotNETCommon
{
///
/// Representation of an absolute directory path. Allows fast hashing and comparisons.
///
[Serializable]
public class DirectoryReference : FileSystemReference, IEquatable
{
///
/// Default constructor.
///
/// Path to this directory.
public DirectoryReference(string InPath)
: base(FixTrailingPathSeparator(Path.GetFullPath(InPath)))
{
}
///
/// Construct a DirectoryReference from a DirectoryInfo object.
///
/// Path to this file
public DirectoryReference(DirectoryInfo InInfo)
: base(FixTrailingPathSeparator(InInfo.FullName))
{
}
///
/// Constructor for creating a directory object directly from two strings.
///
///
///
protected DirectoryReference(string InFullName, string InCanonicalName)
: base(InFullName, InCanonicalName)
{
}
///
/// Ensures that the correct trailing path separator is appended. On Windows, the root directory (eg. C:\) always has a trailing path separator, but no other
/// path does.
///
/// Absolute path to the directory
/// Path to the directory, with the correct trailing path separator
private static string FixTrailingPathSeparator(string DirName)
{
if(DirName.Length == 2 && DirName[1] == ':')
{
return DirName + Path.DirectorySeparatorChar;
}
else if(DirName.Length == 3 && DirName[1] == ':' && DirName[2] == Path.DirectorySeparatorChar)
{
return DirName;
}
else if(DirName.Length > 1 && DirName[DirName.Length - 1] == Path.DirectorySeparatorChar)
{
return DirName.TrimEnd(Path.DirectorySeparatorChar);
}
else
{
return DirName;
}
}
///
/// Gets the top level directory name
///
/// The name of the directory
public string GetDirectoryName()
{
return Path.GetFileName(FullName);
}
///
/// Gets the directory containing this object
///
/// A new directory object representing the directory containing this object
public DirectoryReference ParentDirectory
{
get
{
if (IsRootDirectory())
{
return null;
}
int ParentLength = CanonicalName.LastIndexOf(Path.DirectorySeparatorChar);
if (ParentLength == 2 && CanonicalName[1] == ':')
{
ParentLength++;
}
return new DirectoryReference(FullName.Substring(0, ParentLength), CanonicalName.Substring(0, ParentLength));
}
}
///
/// Gets the parent directory for a file
///
/// The file to get directory for
/// The full directory name containing the given file
public static DirectoryReference GetParentDirectory(FileReference File)
{
int ParentLength = File.CanonicalName.LastIndexOf(Path.DirectorySeparatorChar);
return new DirectoryReference(File.FullName.Substring(0, ParentLength), File.CanonicalName.Substring(0, ParentLength));
}
///
/// Determines whether this path represents a root directory in the filesystem
///
/// True if this path is a root directory, false otherwise
public bool IsRootDirectory()
{
return CanonicalName[CanonicalName.Length - 1] == Path.DirectorySeparatorChar;
}
///
/// Combine several fragments with a base directory, to form a new directory name
///
/// The base directory
/// Fragments to combine with the base directory
/// The new directory name
public static DirectoryReference Combine(DirectoryReference BaseDirectory, params string[] Fragments)
{
string FullName = FileSystemReference.CombineStrings(BaseDirectory, Fragments);
return new DirectoryReference(FullName, FullName.ToLowerInvariant());
}
///
/// Compares two filesystem object names for equality. Uses the canonical name representation, not the display name representation.
///
/// First object to compare.
/// Second object to compare.
/// True if the names represent the same object, false otherwise
public static bool operator ==(DirectoryReference A, DirectoryReference B)
{
if ((object)A == null)
{
return (object)B == null;
}
else
{
return (object)B != null && A.CanonicalName == B.CanonicalName;
}
}
///
/// Compares two filesystem object names for inequality. Uses the canonical name representation, not the display name representation.
///
/// First object to compare.
/// Second object to compare.
/// False if the names represent the same object, true otherwise
public static bool operator !=(DirectoryReference A, DirectoryReference B)
{
return !(A == B);
}
///
/// Compares against another object for equality.
///
/// other instance to compare.
/// True if the names represent the same object, false otherwise
public override bool Equals(object Obj)
{
return (Obj is DirectoryReference) && ((DirectoryReference)Obj) == this;
}
///
/// Compares against another object for equality.
///
/// other instance to compare.
/// True if the names represent the same object, false otherwise
public bool Equals(DirectoryReference Obj)
{
return Obj == this;
}
///
/// Returns a hash code for this object
///
///
public override int GetHashCode()
{
return CanonicalName.GetHashCode();
}
///
/// Helper function to create a remote directory reference. Unlike normal DirectoryReference objects, these aren't converted to a full path in the local filesystem.
///
/// The absolute path in the remote file system
/// New directory reference
public static DirectoryReference MakeRemote(string AbsolutePath)
{
return new DirectoryReference(AbsolutePath, AbsolutePath.ToLowerInvariant());
}
///
/// Helper function to create a directory reference from a raw platform path. The path provided *MUST* be exactly the same as that returned by Path.GetFullPath().
///
/// The absolute path in the file system
/// New file reference
public static DirectoryReference MakeFromNormalizedFullPath(string AbsolutePath)
{
return new DirectoryReference(AbsolutePath, AbsolutePath.ToLowerInvariant());
}
///
/// Gets the parent directory for a file, or returns null if it's null.
///
/// The file to create a directory reference for
/// The directory containing the file
public static DirectoryReference FromFile(FileReference File)
{
return (File == null)? null : File.Directory;
}
#region System.IO.Directory Wrapper Methods
///
/// Finds the current directory
///
/// The current directory
public static DirectoryReference GetCurrentDirectory()
{
return new DirectoryReference(Directory.GetCurrentDirectory());
}
///
/// Creates a directory
///
/// Location of the directory
public static void CreateDirectory(DirectoryReference Location)
{
Directory.CreateDirectory(Location.FullName);
}
///
/// Deletes a directory
///
/// Location of the directory
public static void Delete(DirectoryReference Location)
{
Directory.Delete(Location.FullName);
}
///
/// Deletes a directory
///
/// Location of the directory
/// Whether to remove directories recursively
public static void Delete(DirectoryReference Location, bool bRecursive)
{
Directory.Delete(Location.FullName, bRecursive);
}
///
/// Checks whether the directory exists
///
/// Location of the directory
/// True if this directory exists
public static bool Exists(DirectoryReference Location)
{
return Directory.Exists(Location.FullName);
}
///
/// Enumerate files from a given directory
///
/// Base directory to search in
/// Sequence of file references
public static IEnumerable EnumerateFiles(DirectoryReference BaseDir)
{
foreach (string FileName in Directory.EnumerateFiles(BaseDir.FullName))
{
yield return FileReference.MakeFromNormalizedFullPath(FileName);
}
}
///
/// Enumerate files from a given directory
///
/// Base directory to search in
/// Pattern for matching files
/// Sequence of file references
public static IEnumerable EnumerateFiles(DirectoryReference BaseDir, string Pattern)
{
foreach (string FileName in Directory.EnumerateFiles(BaseDir.FullName, Pattern))
{
yield return FileReference.MakeFromNormalizedFullPath(FileName);
}
}
///
/// Enumerate files from a given directory
///
/// Base directory to search in
/// Pattern for matching files
/// Options for the search
/// Sequence of file references
public static IEnumerable EnumerateFiles(DirectoryReference BaseDir, string Pattern, SearchOption Option)
{
foreach (string FileName in Directory.EnumerateFiles(BaseDir.FullName, Pattern, Option))
{
yield return FileReference.MakeFromNormalizedFullPath(FileName);
}
}
///
/// Enumerate subdirectories in a given directory
///
/// Base directory to search in
/// Sequence of directory references
public static IEnumerable EnumerateDirectories(DirectoryReference BaseDir)
{
foreach (string DirectoryName in Directory.EnumerateDirectories(BaseDir.FullName))
{
yield return DirectoryReference.MakeFromNormalizedFullPath(DirectoryName);
}
}
///
/// Enumerate subdirectories in a given directory
///
/// Base directory to search in
/// Pattern for matching directories
/// Sequence of directory references
public static IEnumerable EnumerateDirectories(DirectoryReference BaseDir, string Pattern)
{
foreach (string DirectoryName in Directory.EnumerateDirectories(BaseDir.FullName, Pattern))
{
yield return DirectoryReference.MakeFromNormalizedFullPath(DirectoryName);
}
}
///
/// Enumerate subdirectories in a given directory
///
/// Base directory to search in
/// Pattern for matching files
/// Options for the search
/// Sequence of directory references
public static IEnumerable EnumerateDirectories(DirectoryReference BaseDir, string Pattern, SearchOption Option)
{
foreach (string DirectoryName in Directory.EnumerateDirectories(BaseDir.FullName, Pattern, Option))
{
yield return DirectoryReference.MakeFromNormalizedFullPath(DirectoryName);
}
}
///
/// Sets the current directory
///
/// Location of the new current directory
public static void SetCurrentDirectory(DirectoryReference Location)
{
Directory.SetCurrentDirectory(Location.FullName);
}
#endregion
}
///
/// Extension methods for passing DirectoryReference arguments
///
public static class DirectoryReferenceExtensionMethods
{
///
/// Manually serialize a file reference to a binary stream.
///
/// Binary writer to write to
/// The directory reference to write
public static void Write(this BinaryWriter Writer, DirectoryReference Directory)
{
Writer.Write((Directory == null) ? String.Empty : Directory.FullName);
}
///
/// Manually deserialize a directory reference from a binary stream.
///
/// Binary reader to read from
/// New DirectoryReference object
public static DirectoryReference ReadDirectoryReference(this BinaryReader Reader)
{
string FullName = Reader.ReadString();
return (FullName.Length == 0) ? null : DirectoryReference.MakeFromNormalizedFullPath(FullName);
}
}
}