From 2ad3b9e0f275e0d908a2ebc5a04eb2a9230bee16 Mon Sep 17 00:00:00 2001 From: EveryGameSPlay Date: Wed, 14 Dec 2022 15:07:34 +0300 Subject: [PATCH] Added relative file support --- Automata/IO/DirectoryExtensions.cs | 46 +++++++++++++ Automata/IO/IDirectory.cs | 8 +-- Automata/IO/IFile.cs | 4 +- Automata/IO/IO.cs | 67 ++++++++++++++----- Automata/IO/IOShared.cs | 25 +++++++ Automata/IO/Relatives/IRelativeDirectory.cs | 21 ++++++ Automata/IO/Relatives/IRelativeFile.cs | 22 ++++++ .../Relatives/RelativeDirectoryExtensions.cs | 10 +++ .../IO/Relatives/RelativeFileExtensions.cs | 9 +++ 9 files changed, 189 insertions(+), 23 deletions(-) create mode 100644 Automata/IO/IOShared.cs create mode 100644 Automata/IO/Relatives/IRelativeDirectory.cs create mode 100644 Automata/IO/Relatives/IRelativeFile.cs create mode 100644 Automata/IO/Relatives/RelativeDirectoryExtensions.cs create mode 100644 Automata/IO/Relatives/RelativeFileExtensions.cs diff --git a/Automata/IO/DirectoryExtensions.cs b/Automata/IO/DirectoryExtensions.cs index cfb60f6..63bbcde 100644 --- a/Automata/IO/DirectoryExtensions.cs +++ b/Automata/IO/DirectoryExtensions.cs @@ -24,6 +24,52 @@ public static async Task> Files(this IDirectory dir) return direcotryInfo.GetFiles().Select(x => new File(dir, x.Name)).ToList(); } + public static async IAsyncEnumerable EnumerateFiles(this IDirectory dir) + { + var directoryInfo = new DirectoryInfo(dir.Path); + foreach (var enumerateFile in directoryInfo.EnumerateFiles()) + { + yield return dir.File(enumerateFile.Name); + } + } + + public static async Task> FilesDeep(this IDirectory root) + { + var files = new List(); + foreach (var dir in await root.Directories()) + { + files.AddRange(await FilesDeep(dir)); + } + + var rootFiles = await root.Files(); + files.AddRange(rootFiles); + return files; + } + + public static async Task> FilesDeep(this IDirectory root, Predicate predicate) + { + var files = new List(); + foreach (var dir in await root.Directories()) + { + files.AddRange(await FilesDeep(dir, predicate)); + } + + var rootFiles = await root.Files(); + files.AddRange(rootFiles.Where(x => predicate(x))); + return files; + } + + public static async IAsyncEnumerable EnumerateFilesDeep(this IDirectory root) + { + await foreach (var enumerateFile in root.EnumerateFiles()) + yield return enumerateFile; + + // Проходим по всем подпапкам + foreach (var directory in await root.Directories()) + await foreach (var file in directory.EnumerateFilesDeep()) + yield return file; + } + public static async Task> Directories(this IDirectory dir) { var dirInfo = new DirectoryInfo(dir.Path); diff --git a/Automata/IO/IDirectory.cs b/Automata/IO/IDirectory.cs index 194bf27..ded9130 100644 --- a/Automata/IO/IDirectory.cs +++ b/Automata/IO/IDirectory.cs @@ -2,22 +2,22 @@ namespace Automata.IO; public interface IDirectory : IO { + IDirectory? Root { get; } } public sealed class Directory : IDirectory { + public string Path { get; } public IDirectory? Root { get; } public Directory(string path) { - Path = IOShared.FileSystem.Path.GetFullPath(path + "/"); + Path = IO.CorrectSlash(path + "/"); } public Directory(IDirectory root, string name) { Root = root; - Path = IOShared.FileSystem.Path.GetFullPath(Root.Path + "/" + name); + Path = IO.CorrectSlash(Root.Path + "/" + name); } - - public string Path { get; } } \ No newline at end of file diff --git a/Automata/IO/IFile.cs b/Automata/IO/IFile.cs index d516a03..d18c550 100644 --- a/Automata/IO/IFile.cs +++ b/Automata/IO/IFile.cs @@ -8,14 +8,14 @@ public interface IFile : IO public sealed class File : IFile { + public string Path { get; } public IDirectory Directory { get; } public string Name { get; } public File(IDirectory directory, string name) { + Path = IO.CorrectSlash(Directory.Path + "/" + Name); Directory = directory; Name = name; } - - public string Path => IOShared.FileSystem.Path.GetFullPath(Directory.Path + "/" + Name); } \ No newline at end of file diff --git a/Automata/IO/IO.cs b/Automata/IO/IO.cs index 9e82b3f..92b4614 100644 --- a/Automata/IO/IO.cs +++ b/Automata/IO/IO.cs @@ -1,30 +1,63 @@ -using System.IO.Abstractions; +using System.Text; namespace Automata.IO; public interface IO { - public string Path { get; } -} - -public static class IOShared -{ - static IOShared() - { - FileSystem = null; - } + string Path { get; } - private static IFileSystem _fileSystem = null!; - public static IFileSystem FileSystem + static string CorrectSlash(string path) { - get => _fileSystem; - set + var builder = new StringBuilder(path.Length); + for (var i = 0; i < path.Length; i++) { - if (value == null) + var c = path[i]; + switch (c) { - value = new FileSystem(); + case '/': + Slash(ref i, path, builder); break; + case '\\': + Slash(ref i, path, builder); break; + default: builder.Append(c); + break; } - _fileSystem = value; } + void Slash(ref int index, string source, StringBuilder builder) + { + builder.Append('/'); + index++; + for (;index < source.Length; index++) + { + var c = source[index]; + if (c == '/' || c == '\\') + continue; + index--; + return; + } + } + return builder.ToString(); + } +} + +// ReSharper disable once InconsistentNaming +public interface RelativeIO : IO +{ + public static string SubtractLeft(string leftPath, string fullPath) + => IO.CorrectSlash(fullPath).Substring(IO.CorrectSlash(leftPath).Length); + + public static IRelativeDirectory RelativeDirectory( + string leftPath, string fullPath) + { + return new RelativeDirectory(SubtractLeft(leftPath, fullPath)); + } + + public static IRelativeFile RelativeFile(string leftPath, string fullPath) + { + var relativePath = SubtractLeft(leftPath, fullPath); + var directoryPath = IOShared.FileSystem.Path.GetDirectoryName(relativePath); + var filename = IOShared.FileSystem.Path.GetFileName(relativePath); + + return new RelativeFile(new RelativeDirectory(directoryPath), filename); } } + diff --git a/Automata/IO/IOShared.cs b/Automata/IO/IOShared.cs new file mode 100644 index 0000000..eb5ec83 --- /dev/null +++ b/Automata/IO/IOShared.cs @@ -0,0 +1,25 @@ +using System.IO.Abstractions; + +namespace Automata.IO; +// ReSharper disable once InconsistentNaming +public static class IOShared +{ + static IOShared() + { + FileSystem = null; + } + + private static IFileSystem _fileSystem = null!; + public static IFileSystem FileSystem + { + get => _fileSystem; + set + { + if (value == null) + { + value = new FileSystem(); + } + _fileSystem = value; + } + } +} \ No newline at end of file diff --git a/Automata/IO/Relatives/IRelativeDirectory.cs b/Automata/IO/Relatives/IRelativeDirectory.cs new file mode 100644 index 0000000..2eee2c0 --- /dev/null +++ b/Automata/IO/Relatives/IRelativeDirectory.cs @@ -0,0 +1,21 @@ +namespace Automata.IO; + +public interface IRelativeDirectory : IO +{ + +} + +public class RelativeDirectory : IRelativeDirectory +{ + public string Path { get; } + + public RelativeDirectory(string path) + { + Path = IO.CorrectSlash(path); + } + + public RelativeDirectory(IRelativeDirectory root, string name) + { + Path = IO.CorrectSlash(root.Path + "/" + name); + } +} \ No newline at end of file diff --git a/Automata/IO/Relatives/IRelativeFile.cs b/Automata/IO/Relatives/IRelativeFile.cs new file mode 100644 index 0000000..4ce2a89 --- /dev/null +++ b/Automata/IO/Relatives/IRelativeFile.cs @@ -0,0 +1,22 @@ +namespace Automata.IO; + +public interface IRelativeFile : IO +{ + IRelativeDirectory RelativeRoot { get; } + string Name { get; } +} + +public class RelativeFile : IRelativeFile +{ + public string Path { get; } + + public IRelativeDirectory RelativeRoot { get; } + public string Name { get; } + + public RelativeFile(IRelativeDirectory root, string name) + { + RelativeRoot = root; + Name = name; + Path = IO.CorrectSlash(RelativeRoot.Path + name); + } +} \ No newline at end of file diff --git a/Automata/IO/Relatives/RelativeDirectoryExtensions.cs b/Automata/IO/Relatives/RelativeDirectoryExtensions.cs new file mode 100644 index 0000000..99b0e95 --- /dev/null +++ b/Automata/IO/Relatives/RelativeDirectoryExtensions.cs @@ -0,0 +1,10 @@ +namespace Automata.IO; + +public static class RelativeDirectoryExtensions +{ + public static IRelativeDirectory Directory(this IRelativeDirectory root, string name) + => new RelativeDirectory(root, name); + + public static IRelativeFile File(this IRelativeDirectory dir, string file) + => new RelativeFile(dir, file); +} \ No newline at end of file diff --git a/Automata/IO/Relatives/RelativeFileExtensions.cs b/Automata/IO/Relatives/RelativeFileExtensions.cs new file mode 100644 index 0000000..27ac15a --- /dev/null +++ b/Automata/IO/Relatives/RelativeFileExtensions.cs @@ -0,0 +1,9 @@ +namespace Automata.IO; + +public static class RelativeFileExtensions +{ + public static IRelativeFile RelativeFile(this IFile file, IDirectory excludeDirectoryPath) + { + return RelativeIO.RelativeFile(excludeDirectoryPath.Path, file.Path); + } +} \ No newline at end of file