IOPath
This commit is contained in:
parent
fe980d5a82
commit
563eabb6c4
@ -30,16 +30,13 @@ public static class Program
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string path = "file";
|
IOPath path = "file";
|
||||||
string path2 = path + "_temp";
|
IOPath path2 = "dir/"+ path + "_temp";
|
||||||
// Ensure that the target does not exist.
|
File.Create(path);
|
||||||
File.Delete(path2);
|
File.Copy(path, path2, true);
|
||||||
// Copy the file.
|
|
||||||
File.Copy(path, path2);
|
|
||||||
System.Console.WriteLine("{0} was copied to {1}.", path, path2);
|
System.Console.WriteLine("{0} was copied to {1}.", path, path2);
|
||||||
// Delete the newly created file.
|
Directory.Copy(path2.ParentDir(), "dir2/c/", true);
|
||||||
File.Delete(path2);
|
System.Console.WriteLine($"dir/c/:\n"+Directory.GetAllFiles("dir2\\c").MergeToString("\n\t"));
|
||||||
System.Console.WriteLine("{0} was successfully deleted.", path2);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new LaunchArgumentParser().WithNoExit().ParseAndHandle(args);
|
new LaunchArgumentParser().WithNoExit().ParseAndHandle(args);
|
||||||
|
|||||||
@ -29,10 +29,10 @@ public static class DependencyResolver
|
|||||||
_ => throw new Exception($"unsupported platform {RuntimeInformation.ProcessArchitecture}")
|
_ => throw new Exception($"unsupported platform {RuntimeInformation.ProcessArchitecture}")
|
||||||
};
|
};
|
||||||
|
|
||||||
string[] possibleLibDirs =
|
IOPath[] possibleLibDirs = new []
|
||||||
{
|
{
|
||||||
Path.Concat("runtimes", $"{os}"),
|
Path.Concat("runtimes", os),
|
||||||
Path.Concat("runtimes", $"{os}", "native"),
|
Path.Concat("runtimes", os, "native"),
|
||||||
Path.Concat("runtimes", $"{os}-{arch}"),
|
Path.Concat("runtimes", $"{os}-{arch}"),
|
||||||
Path.Concat("runtimes", $"{os}-{arch}", "native")
|
Path.Concat("runtimes", $"{os}-{arch}", "native")
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,125 +2,101 @@
|
|||||||
|
|
||||||
public static class Directory
|
public static class Directory
|
||||||
{
|
{
|
||||||
public static bool Exists(string dir, bool separatorsFixed)
|
public static bool Exists(IOPath dir) => System.IO.Directory.Exists(dir.Str);
|
||||||
{
|
|
||||||
if(!separatorsFixed)
|
|
||||||
dir = Path.FixSeparators(dir);
|
|
||||||
return System.IO.Directory.Exists(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// создает папку, если её не существует
|
/// создает папку, если её не существует
|
||||||
public static void Create(string dir, bool separatorsFixed)
|
public static void Create(IOPath dir)
|
||||||
{
|
{
|
||||||
if(!separatorsFixed)
|
if (Exists(dir)) return;
|
||||||
dir = Path.FixSeparators(dir);
|
|
||||||
if (!Exists(dir))
|
// creation of parent directories
|
||||||
|
if (dir.Contains(Path.Sep))
|
||||||
{
|
{
|
||||||
// проверяет существование папки, в которой нужно создать dir
|
var parentDir = dir.ParentDir();
|
||||||
if (dir.Contains(Path.Sep))
|
if(!Exists(parentDir))
|
||||||
{
|
Create(parentDir);
|
||||||
string parentDir = dir.Remove(dir.LastIndexOf(Path.Sep));
|
|
||||||
if(!Exists(parentDir,true))
|
|
||||||
Create(parentDir,true);
|
|
||||||
}
|
|
||||||
else System.IO.Directory.CreateDirectory(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.IO.Directory.CreateDirectory(dir.Str);
|
||||||
}
|
}
|
||||||
/// копирует все файлы и папки
|
/// копирует все файлы и папки
|
||||||
public static void Copy(string source_dir, string new_dir, bool owerwrite)
|
public static void Copy(IOPath sourceDir, IOPath newDir, bool owerwrite)
|
||||||
{
|
{
|
||||||
Copy_internal(source_dir, new_dir, owerwrite, null);
|
Copy_internal(sourceDir, newDir, owerwrite, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// копирует все файлы и папки и выдаёт список конфликтующих файлов
|
/// копирует все файлы и папки и выдаёт список конфликтующих файлов
|
||||||
public static void Copy(string source_dir, string new_dir, bool owerwrite, out List<string> conflicts)
|
public static void Copy(IOPath sourceDir, IOPath newDir, bool owerwrite, out List<IOPath> conflicts)
|
||||||
{
|
{
|
||||||
conflicts = new List<string>();
|
conflicts = new List<IOPath>();
|
||||||
Copy_internal(source_dir, new_dir, owerwrite, conflicts);
|
Copy_internal(sourceDir, newDir, owerwrite, conflicts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Copy_internal(string source_dir, string new_dir, bool owerwrite, List<string> conflicts)
|
private static void Copy_internal(IOPath sourceDir, IOPath newDir, bool owerwrite, List<IOPath> conflicts)
|
||||||
{
|
{
|
||||||
bool countConflicts = conflicts is null;
|
bool countConflicts = conflicts is not null;
|
||||||
List<string> files = GetAllFiles(source_dir);
|
List<IOPath> files = GetAllFiles(sourceDir);
|
||||||
Create(new_dir);
|
Create(newDir);
|
||||||
for (int i = 0; i < files.Count; i++)
|
for (int i = 0; i < files.Count; i++)
|
||||||
{
|
{
|
||||||
string newfile = Path.ReplaceBase(files[i], source_dir, new_dir);
|
var newfile = files[i].ReplaceBase(sourceDir, newDir);
|
||||||
if (countConflicts && File.Exists(newfile))
|
if (countConflicts && File.Exists(newfile))
|
||||||
conflicts!.Add(newfile);
|
conflicts.Add(newfile);
|
||||||
File.Copy(files[i], newfile, owerwrite);
|
File.Copy(files[i], newfile, owerwrite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// удаляет папку со всеми подпапками и файлами
|
/// удаляет папку со всеми подпапками и файлами
|
||||||
public static void Delete(string dir, bool separatorsFixed)
|
public static void Delete(IOPath dir) =>
|
||||||
{
|
System.IO.Directory.Delete(dir.Str, true);
|
||||||
if(!separatorsFixed)
|
|
||||||
dir = Path.FixSeparators(dir);
|
|
||||||
System.IO.Directory.Delete(dir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] GetFiles(string dir, bool separatorsFixed)
|
public static IOPath[] GetFiles(IOPath dir) =>
|
||||||
{
|
IOPath.ArrayCast(System.IO.Directory.GetFiles(dir.Str));
|
||||||
if (!separatorsFixed)
|
|
||||||
dir = Path.FixSeparators(dir);
|
|
||||||
return System.IO.Directory.GetFiles(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] GetFiles(string dir, string searchPattern, bool separatorsFixed)
|
public static IOPath[] GetFiles(IOPath dir, string searchPattern) =>
|
||||||
{
|
IOPath.ArrayCast(System.IO.Directory.GetFiles(dir.Str, searchPattern));
|
||||||
if (!separatorsFixed)
|
|
||||||
dir = Path.FixSeparators(dir);
|
|
||||||
return System.IO.Directory.GetFiles(dir, searchPattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] GetDirectories(string dir, bool separatorsFixed)
|
public static IOPath[] GetDirectories(IOPath dir) =>
|
||||||
{
|
IOPath.ArrayCast(System.IO.Directory.GetDirectories(dir.Str));
|
||||||
if (!separatorsFixed)
|
|
||||||
dir = Path.FixSeparators(dir);
|
public static IOPath[] GetDirectories(IOPath dir, string searchPattern) =>
|
||||||
return System.IO.Directory.GetDirectories(dir);
|
IOPath.ArrayCast(System.IO.Directory.GetDirectories(dir.Str, searchPattern));
|
||||||
}
|
|
||||||
|
|
||||||
/// выдает список всех файлов
|
/// выдает список всех файлов
|
||||||
public static List<string> GetAllFiles(string dir)
|
public static List<IOPath> GetAllFiles(IOPath dir)
|
||||||
{
|
{
|
||||||
var all_files = new List<string>();
|
return GetAllFiles_internal(dir, null);
|
||||||
string[] cur_files = GetFiles(dir);
|
|
||||||
for (int i = 0; i < cur_files.Length; i++)
|
|
||||||
all_files.Add(cur_files[i]);
|
|
||||||
string[] cur_subdirs = GetDirectories(dir);
|
|
||||||
for (int i = 0; i < cur_subdirs.Length; i++)
|
|
||||||
all_files.AddRange(GetAllFiles(cur_subdirs[i]));
|
|
||||||
return all_files;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// выдает список всех файлов и подпапок в папке
|
/// выдает список всех файлов и подпапок в папке
|
||||||
public static List<string> GetAllFiles(string dir, ref List<string> all_subdirs)
|
public static List<IOPath> GetAllFiles(IOPath dir, out List<IOPath> all_subdirs)
|
||||||
{
|
{
|
||||||
var all_files = new List<string>();
|
all_subdirs = new List<IOPath>();
|
||||||
string[] cur_files = GetFiles(dir);
|
return GetAllFiles_internal(dir, all_subdirs);
|
||||||
|
}
|
||||||
|
private static List<IOPath> GetAllFiles_internal(IOPath dir, List<IOPath> all_subdirs)
|
||||||
|
{
|
||||||
|
bool rememberSubdirs = all_subdirs is not null;
|
||||||
|
var all_files = new List<IOPath>();
|
||||||
|
IOPath[] cur_files = GetFiles(dir);
|
||||||
for (int i = 0; i < cur_files.Length; i++)
|
for (int i = 0; i < cur_files.Length; i++)
|
||||||
all_files.Add(cur_files[i]);
|
all_files.Add(cur_files[i]);
|
||||||
string[] cur_subdirs = GetDirectories(dir);
|
IOPath[] cur_subdirs = GetDirectories(dir);
|
||||||
for (int i = 0; i < cur_subdirs.Length; i++)
|
for (int i = 0; i < cur_subdirs.Length; i++)
|
||||||
{
|
{
|
||||||
all_subdirs.Add(cur_subdirs[i]);
|
if(rememberSubdirs)
|
||||||
all_files.AddRange(GetAllFiles(cur_subdirs[i], ref all_subdirs));
|
all_subdirs.Add(cur_subdirs[i]);
|
||||||
|
all_files.AddRange(GetAllFiles_internal(cur_subdirs[i], all_subdirs));
|
||||||
}
|
}
|
||||||
return all_files;
|
return all_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory();
|
public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
public static void CreateSymlink(string sourcePath, string symlinkPath, bool separatorsFixed)
|
public static void CreateSymlink(string sourcePath, string symlinkPath)
|
||||||
{
|
{
|
||||||
if (!separatorsFixed)
|
if (symlinkPath.Contains(Path.Sep))
|
||||||
{
|
Create(Path.ParentDir(symlinkPath));
|
||||||
sourcePath = Path.FixSeparators(sourcePath);
|
|
||||||
symlinkPath = Path.FixSeparators(symlinkPath);
|
|
||||||
}
|
|
||||||
Create(Path.ParentDir(symlinkPath, true), true);
|
|
||||||
if (!Symlink.CreateSymbolicLink(symlinkPath, sourcePath, Symlink.SymlinkTarget.Directory))
|
if (!Symlink.CreateSymbolicLink(symlinkPath, sourcePath, Symlink.SymlinkTarget.Directory))
|
||||||
throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkPath}, {sourcePath})");
|
throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkPath}, {sourcePath})");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,60 +3,45 @@
|
|||||||
public static class File
|
public static class File
|
||||||
{
|
{
|
||||||
/// возвращает размер файла в байтах
|
/// возвращает размер файла в байтах
|
||||||
public static long GetSize(string file, bool separatorsFixed)
|
public static long GetSize(IOPath file) => new System.IO.FileInfo(file.Str).Length;
|
||||||
{
|
|
||||||
if (!separatorsFixed)
|
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
return new System.IO.FileInfo(file).Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Exists(string file, bool separatorsFixed)
|
public static bool Exists(IOPath file)
|
||||||
{
|
{
|
||||||
if (!separatorsFixed)
|
if (System.IO.File.Exists(file.Str)) return true;
|
||||||
file = Path.FixSeparators(file);
|
return false;
|
||||||
return System.IO.File.Exists(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// если файл не существует, создаёт файл с папками из его пути и закрывает этот фвйл
|
/// если файл не существует, создаёт файл с папками из его пути и закрывает этот фвйл
|
||||||
public static void Create(string file, bool separatorsFixed)
|
public static void Create(IOPath file)
|
||||||
{
|
{
|
||||||
if (!separatorsFixed)
|
if (Exists(file)) return;
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
if (!Exists(file, true))
|
Directory.Create(file.ParentDir());
|
||||||
{
|
using System.IO.FileStream stream = System.IO.File.Create(file.Str);
|
||||||
Directory.Create(Path.ParentDir(file, true), true);
|
stream.Close();
|
||||||
using System.IO.FileStream stream = System.IO.File.Create(file);
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Copy(string srcPath, string newPath, bool overwrite = false, bool separatorsFixed)
|
public static void Copy(IOPath srcPath, IOPath newPath, bool overwrite)
|
||||||
{
|
{
|
||||||
if (!separatorsFixed)
|
|
||||||
{
|
|
||||||
srcPath = Path.FixSeparators(srcPath);
|
|
||||||
newPath = Path.FixSeparators(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Exists(newPath))
|
if (Exists(newPath))
|
||||||
{
|
{
|
||||||
if(overwrite) System.IO.File.Delete(newPath);
|
if(overwrite) System.IO.File.Delete(newPath.Str);
|
||||||
else throw new Exception($"file <{newPath}> alredy exists");
|
else throw new Exception($"file <{newPath}> alredy exists");
|
||||||
}
|
}
|
||||||
else Directory.Create(Path.ParentDir(newPath, true));
|
else Directory.Create(newPath.ParentDir());
|
||||||
using var srcFile=System.IO.File.Open(srcPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
|
using var srcFile=System.IO.File.Open(srcPath.Str, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
|
||||||
using var newFile=System.IO.File.Open(newPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
using var newFile=System.IO.File.Open(newPath.Str, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
||||||
srcFile.CopyTo(newFile);
|
srcFile.CopyTo(newFile);
|
||||||
srcFile.Close();
|
srcFile.Close();
|
||||||
newFile.Flush();
|
newFile.Flush();
|
||||||
newFile.Close();
|
newFile.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Delete(string file) => System.IO.File.Delete(Path.FixSeparators(file));
|
public static void Delete(IOPath file) => System.IO.File.Delete(file.Str);
|
||||||
|
|
||||||
public static byte[] ReadAllBytes(string file)
|
public static byte[] ReadAllBytes(IOPath file)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
using System.IO.FileStream stream = OpenRead(file);
|
using System.IO.FileStream stream = OpenRead(file);
|
||||||
int size = GetSize(file).ToInt();
|
int size = GetSize(file).ToInt();
|
||||||
byte[] output = new byte[size];
|
byte[] output = new byte[size];
|
||||||
@ -66,58 +51,52 @@ public static class File
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadAllText(string file) => ReadAllBytes(file).BytesToString(StringConverter.UTF8);
|
public static string ReadAllText(IOPath file) => ReadAllBytes(file).BytesToString(StringConverter.UTF8);
|
||||||
|
|
||||||
public static void WriteAllBytes(string file, byte[] content)
|
public static void WriteAllBytes(IOPath file, byte[] content)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
using System.IO.FileStream stream = OpenWrite(file);
|
using System.IO.FileStream stream = OpenWrite(file);
|
||||||
stream.Write(content, 0, content.Length);
|
stream.Write(content, 0, content.Length);
|
||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteAllText(string file, string content) => WriteAllBytes(file, content.ToBytes(StringConverter.UTF8));
|
public static void WriteAllText(IOPath file, string content) => WriteAllBytes(file, content.ToBytes(StringConverter.UTF8));
|
||||||
|
|
||||||
public static void AppendAllBytes(string file, byte[] content)
|
public static void AppendAllBytes(IOPath file, byte[] content)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
using System.IO.FileStream stream = OpenAppend(file);
|
using System.IO.FileStream stream = OpenAppend(file);
|
||||||
stream.Write(content, 0, content.Length);
|
stream.Write(content, 0, content.Length);
|
||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AppendAllText(string file, string content) => AppendAllBytes(file, content.ToBytes(StringConverter.UTF8));
|
public static void AppendAllText(IOPath file, string content) => AppendAllBytes(file, content.ToBytes(StringConverter.UTF8));
|
||||||
|
|
||||||
public static System.IO.FileStream OpenRead(string file)
|
public static System.IO.FileStream OpenRead(IOPath file)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
if (!Exists(file))
|
||||||
if (Exists(file))
|
throw new Exception($"file not found: <{file}>");
|
||||||
return System.IO.File.Open(file, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
|
return System.IO.File.Open(file.Str, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
|
||||||
throw new Exception($"file not found: <{file}>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static System.IO.FileStream OpenWrite(string file)
|
public static System.IO.FileStream OpenWrite(IOPath file)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
if (Exists(file))
|
if (Exists(file))
|
||||||
Delete(file);
|
Delete(file);
|
||||||
Create(file);
|
Create(file);
|
||||||
return System.IO.File.Open(file, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
return System.IO.File.Open(file.Str, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
||||||
}
|
}
|
||||||
public static System.IO.FileStream OpenAppend(string file)
|
public static System.IO.FileStream OpenAppend(IOPath file)
|
||||||
{
|
{
|
||||||
file = Path.FixSeparators(file);
|
|
||||||
Create(file);
|
Create(file);
|
||||||
return System.IO.File.Open(file, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
return System.IO.File.Open(file.Str, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CreateSymlink(string sourceName, string symlinkName)
|
public static void CreateSymlink(IOPath sourcePath, IOPath symlinkPath)
|
||||||
{
|
{
|
||||||
sourceName = Path.FixSeparators(sourceName);
|
if (symlinkPath.Contains(Path.Sep))
|
||||||
symlinkName = Path.FixSeparators(symlinkName);
|
Directory.Create(symlinkPath.ParentDir());
|
||||||
if (symlinkName.Contains(Path.Sep))
|
if (!Symlink.CreateSymbolicLink(symlinkPath.Str, sourcePath.Str, Symlink.SymlinkTarget.File))
|
||||||
Directory.Create(symlinkName.Remove(symlinkName.LastIndexOf(Path.Sep)));
|
throw new InvalidOperationException($"some error occured while creating symlink\nFile.CreateSymlink({symlinkPath}, {sourcePath})");
|
||||||
if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.File))
|
|
||||||
throw new InvalidOperationException($"some error occured while creating symlink\nFile.CreateSymlink({symlinkName}, {sourceName})");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
155
DTLib/Filesystem/IOPath.cs
Normal file
155
DTLib/Filesystem/IOPath.cs
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0
|
||||||
|
#define USE_SPAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DTLib.Filesystem;
|
||||||
|
|
||||||
|
public readonly struct IOPath
|
||||||
|
{
|
||||||
|
public readonly string Str;
|
||||||
|
|
||||||
|
public IOPath(string path, bool separatorsFixed=false)
|
||||||
|
{
|
||||||
|
if (!separatorsFixed)
|
||||||
|
{
|
||||||
|
var chars = path.ToCharArray();
|
||||||
|
for(int i=0; i<path.Length; i++)
|
||||||
|
if (chars[i] == Path.NotSep)
|
||||||
|
chars[i] = Path.Sep;
|
||||||
|
Str = new string(chars);
|
||||||
|
}
|
||||||
|
else Str = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOPath(char[] path) : this(new string(path)) {}
|
||||||
|
|
||||||
|
public static IOPath[] ArrayCast(string[] a)
|
||||||
|
{
|
||||||
|
IOPath[] b = new IOPath[a.Length];
|
||||||
|
for (int i = 0; i < a.Length; i++)
|
||||||
|
b[i] = (IOPath)a[i];
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
public static IOPath[] ArrayCast(IList<string> a)
|
||||||
|
{
|
||||||
|
IOPath[] b = new IOPath[a.Count];
|
||||||
|
for (int i = 0; i < a.Count; i++)
|
||||||
|
b[i] = (IOPath)a[i];
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public static IOPath operator +(IOPath a, IOPath b) => Concat(a, b);
|
||||||
|
public static bool operator ==(IOPath a, IOPath b) => a.Str==b.Str;
|
||||||
|
public static bool operator !=(IOPath a, IOPath b) => a.Str!=b.Str;
|
||||||
|
public static implicit operator IOPath(string s) => new(s);
|
||||||
|
public static explicit operator string(IOPath p) => p.Str;
|
||||||
|
public override string ToString() => Str;
|
||||||
|
public override bool Equals(object obj) => Str.Equals(obj);
|
||||||
|
|
||||||
|
public override int GetHashCode() => Str.GetHashCode();
|
||||||
|
|
||||||
|
public char this[int i] => Str[i];
|
||||||
|
public int Length => Str.Length;
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public char[] ToCharArray() => Str.ToCharArray();
|
||||||
|
|
||||||
|
#if USE_SPAN
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public ReadOnlySpan<char> AsSpan() => Str.AsSpan();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Contains(char c) => Str.Contains(c);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Contains(string s) => Str.Contains(s);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Contains(IOPath p) => Str.Contains(p.Str);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool StartsWith(char c) => Str.StartsWith(c);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool StartsWith(string s) => Str.StartsWith(s);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool StartsWith(IOPath p) => Str.StartsWith(p.Str);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool EndsWith(char c) => Str.EndsWith(c);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool EndsWith(string s) => Str.EndsWith(s);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool EndsWith(IOPath p) => Str.EndsWith(p.Str);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Remove(int startIndex) => new(Str.Remove(startIndex), true);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Remove(int startIndex, int count) => new(Str.Remove(startIndex, count), true);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Substring(int startIndex) => new(Str.Substring(startIndex), true);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Substring(int startIndex, int count) => new(Str.Substring(startIndex, count), true);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Replace(char oldChar, char newChar) => new(Str.Replace(oldChar, newChar), true);
|
||||||
|
[Obsolete("use different replace methods")]
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IOPath Replace(string oldStr, string newStr) => new(Str.Replace(oldStr, newStr), true);
|
||||||
|
|
||||||
|
///<inheritdoc cref="string.IndexOf(char)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(char c) => Str.IndexOf(c);
|
||||||
|
///<inheritdoc cref="string.IndexOf(char,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(char c, int startIndex) => Str.IndexOf(c, startIndex);
|
||||||
|
///<inheritdoc cref="string.IndexOf(char,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(char c, int startIndex, int count) => Str.IndexOf(c, startIndex, count);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(string s) => Str.IndexOf(s, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(string s, int startIndex) => Str.IndexOf(s, startIndex, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(string s, int startIndex, int count) => Str.IndexOf(s, startIndex, count, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(IOPath p) => Str.IndexOf(p.Str, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(IOPath p, int startIndex) => Str.IndexOf(p.Str, startIndex, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.IndexOf(string,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(IOPath p, int startIndex, int count) => Str.IndexOf(p.Str, startIndex, count, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(char)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(char c) => Str.LastIndexOf(c);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(char,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(char c, int startLastIndex) => Str.LastIndexOf(c, startLastIndex);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(char,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(char c, int startLastIndex, int count) => Str.LastIndexOf(c, startLastIndex, count);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(string s) => Str.LastIndexOf(s, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(string s, int startLastIndex) => Str.LastIndexOf(s, startLastIndex, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(string s, int startLastIndex, int count) => Str.LastIndexOf(s, startLastIndex, count, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(IOPath p) => Str.LastIndexOf(p.Str, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(IOPath p, int startLastIndex) => Str.LastIndexOf(p.Str, startLastIndex, StringComparison.Ordinal);
|
||||||
|
///<inheritdoc cref="string.LastIndexOf(string,int,int)"/>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int LastIndexOf(IOPath p, int startLastIndex, int count) => Str.LastIndexOf(p.Str, startLastIndex, count, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
@ -1,73 +1,32 @@
|
|||||||
|
#if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0
|
||||||
|
#define USE_SPAN
|
||||||
|
#endif
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DTLib.Filesystem;
|
namespace DTLib.Filesystem;
|
||||||
|
|
||||||
public static class Path
|
public static class Path
|
||||||
{
|
{
|
||||||
|
|
||||||
public static readonly char Sep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '\\' : '/';
|
public static readonly char Sep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '\\' : '/';
|
||||||
private static readonly char NotSep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '/' : '\\' ;
|
public static readonly char NotSep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '/' : '\\' ;
|
||||||
|
|
||||||
/// does not correct separators, use Resolve for correction
|
|
||||||
/// <see cref="Resolve(string[])"/>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static string Concat(string path, string addition)
|
|
||||||
{
|
|
||||||
if (!path.EndsWith(Sep) && !addition.StartsWith(Sep))
|
|
||||||
path += Sep;
|
|
||||||
return path + addition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Concat(string,string)"/>
|
|
||||||
public static string Concat(params string[] parts)
|
|
||||||
{
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.Append(parts[0]);
|
|
||||||
for (int i = 1; i < parts.Length; i++)
|
|
||||||
{
|
|
||||||
char lastC = builder[builder.Length - 1];
|
|
||||||
if(lastC!=Sep && lastC!=NotSep)
|
|
||||||
builder.Append(Sep);
|
|
||||||
builder.Append(parts[i]);
|
|
||||||
}
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string FixSeparators(string path)
|
|
||||||
{
|
|
||||||
var chars = path.ToCharArray();
|
|
||||||
int length = path.Length;
|
|
||||||
for(int i=0; i<length; i++)
|
|
||||||
if (chars[i] == NotSep)
|
|
||||||
chars[i] = Sep;
|
|
||||||
return new string(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static string Resolve(params string[] parts) => FixSeparators(Concat(parts));
|
public static void ThrowIfEscapes(this IOPath path)
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static string Resolve(string path, string addition) => FixSeparators(Concat(path, addition));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void ThrowIfEscapes(string path)
|
|
||||||
{
|
{
|
||||||
if (path.Contains(".."))
|
if (path.Str.Contains(".."))
|
||||||
throw new Exception($"path <{path}> uses <..>, that's not allowed");
|
throw new Exception($"path <{path}> uses <..>, that's not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces restricted characters in string
|
/// Replaces restricted characters in string
|
||||||
public static string CorrectString(string str)
|
public static IOPath ReplaceRestrictedChars(string str)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0
|
char[] r = str.ToCharArray();
|
||||||
var a = str.AsSpan();
|
|
||||||
#else
|
for (int i = 0; i < str.Length; i++)
|
||||||
var a = str.ToArray();
|
|
||||||
#endif
|
|
||||||
char[] r = new char[a.Length];
|
|
||||||
for (int i = 0; i < a.Length; i++)
|
|
||||||
{
|
{
|
||||||
switch (a[i])
|
switch (r[i])
|
||||||
{
|
{
|
||||||
case '/': case '\\':
|
case '/': case '\\':
|
||||||
case ':': case ';':
|
case ':': case ';':
|
||||||
@ -82,44 +41,93 @@ public static class Path
|
|||||||
case '`': case '|': case '=':
|
case '`': case '|': case '=':
|
||||||
r[i] = '_';
|
r[i] = '_';
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
r[i] = a[i];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string(r);
|
return new IOPath(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FileName(string path, bool separatorsFixed)
|
#if !USE_SPAN
|
||||||
|
private static unsafe void CopyTo(this string s, char* b)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < s.Length; i++)
|
||||||
|
b[i] = s[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static IOPath Concat(params IOPath[] parts)
|
||||||
|
{
|
||||||
|
#if USE_SPAN
|
||||||
|
Span<bool>
|
||||||
|
#else
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
bool*
|
||||||
|
#endif
|
||||||
|
needSeparator = stackalloc bool[parts.Length-1];
|
||||||
|
int lengthSum = 0;
|
||||||
|
for (int i = 0; i < parts.Length-1; i++)
|
||||||
|
{
|
||||||
|
lengthSum += parts[i].Length;
|
||||||
|
if (!parts[i].Str.EndsWith(Sep) && !parts[i + 1].Str.StartsWith(Sep))
|
||||||
|
{
|
||||||
|
needSeparator[i] = true;
|
||||||
|
lengthSum++;
|
||||||
|
}
|
||||||
|
else needSeparator[i] = false;
|
||||||
|
}
|
||||||
|
lengthSum += parts[parts.Length-1].Length;
|
||||||
|
#if USE_SPAN
|
||||||
|
Span<char>
|
||||||
|
#else
|
||||||
|
char*
|
||||||
|
#endif
|
||||||
|
buffer = stackalloc char[lengthSum];
|
||||||
|
parts[0].Str.CopyTo(buffer);
|
||||||
|
int copiedChars = parts[0].Length;
|
||||||
|
for (int i = 1; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
if (needSeparator[i-1])
|
||||||
|
buffer[copiedChars++] = Sep;
|
||||||
|
#if USE_SPAN
|
||||||
|
parts[i].Str.CopyTo(buffer.Slice(copiedChars));
|
||||||
|
#else
|
||||||
|
parts[i].Str.CopyTo(buffer+copiedChars);
|
||||||
|
#endif
|
||||||
|
copiedChars += parts[i].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IOPath(new string(buffer), true);
|
||||||
|
#if !USE_SPAN
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IOPath FileName(this IOPath path)
|
||||||
{
|
{
|
||||||
if(!separatorsFixed)
|
|
||||||
path = FixSeparators(path);
|
|
||||||
int i = path.LastIndexOf(Sep);
|
int i = path.LastIndexOf(Sep);
|
||||||
if (i == -1) return path;
|
if (i == -1) return path;
|
||||||
return path.Substring(i+1);
|
return path.Substring(i+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Extension(string path)
|
public static IOPath Extension(this IOPath path)
|
||||||
{
|
{
|
||||||
int i = path.LastIndexOf('.');
|
int i = path.LastIndexOf('.');
|
||||||
if (i == -1) return FileName(path);
|
if (i == -1) return FileName(path);
|
||||||
return path.Substring(i + 1);
|
return path.Substring(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ParentDir(string path, bool separatorsFixed)
|
public static IOPath ParentDir(this IOPath path)
|
||||||
{
|
{
|
||||||
if(!separatorsFixed)
|
|
||||||
path = FixSeparators(path);
|
|
||||||
int i = path.LastIndexOf(Sep);
|
int i = path.LastIndexOf(Sep);
|
||||||
if (i == path.Length - 1) // ends with separator
|
if (i == path.Length - 1) // ends with separator
|
||||||
i = path.LastIndexOf(Sep, 0, i);
|
i = path.LastIndexOf(Sep, i-1);
|
||||||
if (i == -1) // no parent dir
|
if (i == -1) // no parent dir
|
||||||
return $".{Sep}";
|
return $".{Sep}";
|
||||||
return path.Substring(0, i);
|
return path.Remove(i+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReplaceBase(string path, string baseDir, string otherDir)
|
public static IOPath ReplaceBase(this IOPath path, IOPath baseDir, IOPath otherDir)
|
||||||
{
|
{
|
||||||
if (!path.StartsWith(baseDir))
|
if (!path.StartsWith(baseDir))
|
||||||
throw new Exception($"path <{path}> doesnt starts with <{baseDir}");
|
throw new Exception($"path <{path}> doesnt starts with <{baseDir}");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user