tesses-vfs/Tesses.VirtualFilesystem.Base/Class1.cs

1023 lines
33 KiB
C#

/*
Tesses.VirtualFilesystem a library for virtual filesystems in .NET
Copyright (C) 2023 Mike Nolan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Tesses.VirtualFilesystem
{
public sealed class NonExistantPointer : EntryPointer
{
public override bool IsNonExistantPointer => true;
public NonExistantPointer(IVirtualFilesystem fs,UnixPath path) : base(fs,path)
{
}
public override bool Exists => false;
public override string Name { get => Path.Name; set {} }
public override void Delete()
{
}
}
public abstract class EntryPointer
{
public virtual bool IsNonExistantPointer {get{return false;}}
public virtual bool IsFilePointer {get{return false;}}
public virtual bool IsDirectoryPointer {get{return false;}}
public virtual bool IsSymlinkPointer {get{return false;}}
public EntryPointer this[UnixPath path]
{
get{
return _fs.OpenEntry(Path / path);
}
}
public DirectoryPointer AsDirectoryPointer()
{
return new DirectoryPointer(_fs,Path);
}
public FilePointer AsFilePointer()
{
return new FilePointer(_fs,Path);
}
public SymlinkPointer AsSymlinkPointer()
{
return new SymlinkPointer(_fs,Path);
}
internal EntryPointer(IVirtualFilesystem fs)
{
_fs=fs;
}
internal EntryPointer(IVirtualFilesystem fs,UnixPath path) : this(fs)
{
Path = path;
}
protected IVirtualFilesystem _fs;
public IVirtualFilesystem Filesystem {get{return _fs;}}
public UnixPath Path {get;set;}="/";
public abstract string Name {get;set;}
public UnixPath WithPath(UnixPath path)
{
return Path / path;
}
public DirectoryPointer Up()
{
return new DirectoryPointer(_fs,_fs.UpPath(Path));
}
public abstract void Delete();
public abstract bool Exists {get;}
}
public sealed class SymlinkPointer : EntryPointer
{
public override bool IsSymlinkPointer => true;
public SymlinkPointer(IVirtualFilesystem fs,UnixPath path) : base(fs,path)
{
}
private void _setName(string name)
{
UnixPath oldPath = Path;
UnixPath target= Target;
Delete();
Path.Name = name;
Target= target;
}
public override string Name { get => Path.Name; set => _setName(value); }
public override bool Exists => _fs.SymlinkExists(Path);
public override void Delete()
{
if(Exists)
_fs.DeleteFile(Path);
}
public UnixPath Target {
get{
return _fs.ReadLink(Path);
}
set{
Delete();
_fs.CreateSymlink(value,Path);
}
}
public EntryPointer TargetPointer
{
get
{
return _fs.OpenEntry(Target);
}
}
}
public sealed class FilePointer : EntryPointer
{
public override bool IsFilePointer => true;
public FilePointer(IVirtualFilesystem fs,UnixPath path) : base(fs,path)
{
}
public Stream Create()
{
return _fs.Open(Path,FileMode.Create,FileAccess.Write,FileShare.Inheritable);
}
public Stream OpenRead()
{
return _fs.Open(Path,FileMode.Open,FileAccess.Read,FileShare.Read);
}
public Stream OpenWrite()
{
return _fs.Open(Path,FileMode.OpenOrCreate,FileAccess.Write,FileShare.Inheritable);
}
public void WriteAllText(string text,Encoding encoding)
{
using(var f = Create())
StreamHelper.WriteAllText(f,text,encoding);
}
public void WriteAllText(string text)
{
WriteAllText(text,Encoding.UTF8);
}
public string ReadAllText(Encoding encoding)
{
using(var f = OpenRead())
return StreamHelper.ReadAllText(f,encoding);
}
public override bool Exists => _fs.FileExists(Path);
public void WriteAllBytes(byte[] data)
{
using(var f = Create())
StreamHelper.WriteAllBytes(f,data);
}
public byte[] ReadAllBytes()
{
using(var f = OpenRead())
return StreamHelper.ReadAllBytes(f);
}
public override void Delete()
{
_fs.DeleteFile(Path);
}
public override string Name
{
get
{
return Path.Name;
}
set
{
UnixPath old = new UnixPath(Path);
Path.Name = value;
_fs.MoveFile(old,Path);
}
}
}
public class DirectoryPointer : EntryPointer, IEnumerable<EntryPointer>
{
public override bool IsDirectoryPointer => true;
public DirectoryPointer(IVirtualFilesystem fs) : base(fs)
{
}
public DirectoryPointer(IVirtualFilesystem fs,UnixPath path) : this(fs)
{
Path = path;
}
public void Create()
{
_fs.CreateDirectory(Path);
}
public override void Delete()
{
_fs.DeleteDirectory(Path);
}
public void DeleteRecursive()
{
_fs.DeleteDirectory(Path,true);
}
public IVirtualFilesystem SubDirectoryFilesystem {get{return _fs.GetSubdirFilesystem(Path);}}
public DirectoryPointer[] Directories
{
get{
return EnumerateDirectories().ToArray();
}
}
public FilePointer[] Files
{
get{
return EnumerateFiles().ToArray();
}
}
public SymlinkPointer[] Symlinks
{
get{
return EnumerateSymlinks().ToArray();
}
}
public EntryPointer[] Entries
{
get {
return EnumerateEntries().ToArray();
}
}
public IEnumerable<DirectoryPointer> EnumerateDirectories()
{
foreach(var item in _fs.EnumerateDirectories(Path))
{
yield return new DirectoryPointer(_fs,item);
}
}
public IEnumerable<FilePointer> EnumerateFiles()
{
foreach(var item in _fs.EnumerateFiles(Path))
{
yield return new FilePointer(_fs,item);
}
}
public IEnumerable<SymlinkPointer> EnumerateSymlinks()
{
foreach(var item in _fs.EnumerateSymlinks(Path))
{
yield return new SymlinkPointer(_fs,item);
}
}
public static DirectoryPointer operator/(DirectoryPointer pointer,string path)
{
return new DirectoryPointer(pointer._fs,pointer.Path / path);
}
public static DirectoryPointer operator/(DirectoryPointer pointer,UnixPath path)
{
return new DirectoryPointer(pointer._fs,pointer.Path / path);
}
public IEnumerable<EntryPointer> EnumerateEntries()
{
foreach(var item in _fs.EnumerateFileSystemEntries(Path))
{
yield return _fs.OpenEntry(item);
}
}
public IEnumerator<EntryPointer> GetEnumerator()
{
return EnumerateEntries().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return EnumerateEntries().GetEnumerator();
}
public override bool Exists {get{return _fs.DirectoryExists(Path);}}
public override string Name
{
get
{
return Path.Name;
}
set
{
UnixPath old = new UnixPath(Path);
Path.Name = value;
_fs.MoveDirectory(old,Path);
}
}
}
public static class StreamHelper
{
public static string ReadAllText(Stream strm,Encoding enc)
{
using(var sr = new StreamReader(strm,enc))
{
return sr.ReadToEnd();
}
}
public static string ReadAllText(Stream strm)
{
return ReadAllText(strm,Encoding.UTF8);
}
public static byte[] ReadAllBytes(Stream strm)
{
MemoryStream ms=new MemoryStream();
strm.CopyTo(ms);
return ms.ToArray();
}
public static void WriteAllBytes(Stream strm,byte[] data)
{
using(MemoryStream ms = new MemoryStream(data))
ms.CopyTo(strm);
}
public static void WriteAllText(Stream strm,string text,Encoding enc)
{
using(var sw = new StreamWriter(strm,enc))
{
sw.Write(text);
}
}
public static void WriteAllText(Stream strm,string text)
{
WriteAllText(strm,text,Encoding.UTF8);
}
public static string[] ReadAllLines(Stream strm,Encoding enc)
{
List<string> ls = new List<string>();
using(var sr = new StreamReader(strm,enc))
{
string line;
while((line=sr.ReadLine()) != null)
{
ls.Add(line);
}
}
return ls.ToArray();
}
public static string[] ReadAllLines(Stream strm)
{
return ReadAllLines(strm,Encoding.UTF8);
}
public static void WriteAllLines(Stream strm,IEnumerable<string> lines,Encoding enc)
{
using(var sw = new StreamWriter(strm,enc))
{
foreach(var line in lines)
{
sw.WriteLine(line);
}
}
}
public static void WriteAllLines(Stream strm,IEnumerable<string> lines)
{
WriteAllLines(strm,lines,Encoding.UTF8);
}
}
public interface IVirtualFilesystem : IDisposable
{
IVirtualFilesystem GetSubdirFilesystem(UnixPath path);
EntryPointer OpenEntry(UnixPath path);
FilePointer OpenFile(UnixPath path);
SymlinkPointer OpenSymlink(UnixPath path);
DirectoryPointer OpenDirectory();
DirectoryPointer OpenDirectory(UnixPath path);
UnixPath UpPath(UnixPath path);
UnixPath ConvertPathToUnixPath(string path);
string ConvertPathFromUnixPath(UnixPath path);
Stream Open(UnixPath path,FileMode mode,FileAccess access,FileShare share);
Task<Stream> OpenAsync(UnixPath path,FileMode mode,FileAccess access,FileShare share,CancellationToken token=default(CancellationToken));
void CreateDirectory(UnixPath directory);
Task CreateDirectoryAsync(UnixPath directory,CancellationToken token=default(CancellationToken));
IEnumerable<UnixPath> EnumerateFileSystemEntries(UnixPath path);
IEnumerable<UnixPath> EnumerateFiles(UnixPath path);
IEnumerable<UnixPath> EnumerateDirectories(UnixPath path);
IEnumerable<UnixPath> EnumerateSymlinks(UnixPath path);
IAsyncEnumerable<UnixPath> EnumerateFilesAsync(UnixPath path,CancellationToken token=default(CancellationToken));
IAsyncEnumerable<UnixPath> EnumerateDirectoriesAsync(UnixPath path,CancellationToken token=default(CancellationToken));
IAsyncEnumerable<UnixPath> EnumerateSymlinksAsync(UnixPath path,CancellationToken token=default(CancellationToken));
IAsyncEnumerable<UnixPath> EnumerateFileSystemEntriesAsync(UnixPath path,CancellationToken token =default(CancellationToken));
bool DirectoryExists(UnixPath path);
Task<bool> DirectoryExistsAsync(UnixPath path,CancellationToken token=default(CancellationToken));
bool FileExists(UnixPath path);
Task<bool> FileExistsAsync(UnixPath path,CancellationToken token=default(CancellationToken));
void DeleteFile(UnixPath path);
void DeleteDirectory(UnixPath path);
void DeleteDirectory(UnixPath path,bool recursive);
void CreateSymlink(UnixPath src,UnixPath dest);
void CreateHardlink(UnixPath src,UnixPath dest);
UnixPath ReadLink(UnixPath file);
Task<UnixPath> ReadLinkAsync(UnixPath file,CancellationToken token=default(CancellationToken));
bool SymlinkExists(UnixPath file);
Task<bool> SymlinkExistsAsync(UnixPath file,CancellationToken token=default(CancellationToken));
Task CreateSymlinkAsync(UnixPath src,UnixPath dest,CancellationToken token=default(CancellationToken));
Task CreateHardlinkAsync(UnixPath src,UnixPath dest,CancellationToken token=default(CancellationToken));
Task<bool> SameFileSystemAsync(UnixPath src,UnixPath dest,CancellationToken token=default(CancellationToken));
bool SameFileSystem(UnixPath src,UnixPath dest);
bool CanHandleSymlinks(UnixPath path);
Task DeleteFileAsync(UnixPath path,CancellationToken token=default(CancellationToken));
Task DeleteDirectoryAsync(UnixPath path,CancellationToken token=default(CancellationToken));
Task DeleteDirectoryAsync(UnixPath path,bool recursive,CancellationToken token=default(CancellationToken));
bool CanWatch(UnixPath path);
IVirtualWatcher WatchDirectory(UnixPath dir);
void MoveFile(UnixPath src,UnixPath dest);
void MoveDirectory(UnixPath src,UnixPath dest);
Task MoveFileAsync(UnixPath src,UnixPath dest);
Task MoveDirectoryAsync(UnixPath src,UnixPath dest);
DateTime GetCreationTime(UnixPath path);
DateTime GetLastAccessTime(UnixPath path);
DateTime GetLastWriteTime(UnixPath path);
void SetCreationTime(UnixPath path,DateTime time);
void SetLastAccessTime(UnixPath path,DateTime time);
void SetLastWriteTime(UnixPath path,DateTime time);
void SetAttributes(UnixPath path,FileAttributes attributes);
FileAttributes GetAttributes(UnixPath path);
Task<DateTime> GetCreationTimeAsync(UnixPath path,CancellationToken token=default(CancellationToken));
Task<DateTime> GetLastAccessTimeAsync(UnixPath path,CancellationToken token=default(CancellationToken));
Task<DateTime> GetLastWriteTimeAsync(UnixPath path,CancellationToken token=default(CancellationToken));
Task SetCreationTimeAsync(UnixPath path,DateTime time,CancellationToken token=default(CancellationToken));
Task SetLastAccessTimeAsync(UnixPath path,DateTime time,CancellationToken token=default(CancellationToken));
Task SetLastWriteTimeAsync(UnixPath path,DateTime time,CancellationToken token=default(CancellationToken));
Task SetAttributesAsync(UnixPath path,FileAttributes attributes,CancellationToken token=default(CancellationToken));
Task<FileAttributes> GetAttributesAsync(UnixPath path,CancellationToken token=default(CancellationToken));
}
public interface IVirtualWatcher : IDisposable
{
event EventHandler<VirtualWatcherChangedArgs> Changed;
event EventHandler<VirtualWatcherChangedArgs> Created;
event EventHandler<VirtualWatcherChangedArgs> Deleted;
event EventHandler<VirtualWatcherRenamedEventArgs> Renamed;
event EventHandler<ErrorEventArgs> Error;
/// <summary>
/// Implementation-defined buffer size for storing events.
/// </summary>
int InternalBufferSize { get; set; }
/// <summary>
/// Implementation-defined filters for filtering events.
/// </summary>
NotifyFilters NotifyFilter { get; set; }
/// <summary>
/// True to enable raising events, false to never raise them. Default false.
/// </summary>
bool EnableRaisingEvents { get; set; }
/// <summary>
/// File name and extension filter. Use <c>"*"</c> to specify variable length placeholder, <c>"?"</c>
/// for a single character placeholder. Default is <c>"*.*"</c> for all files.
/// </summary>
string Filter { get; set; }
/// <summary>
/// True to watch all subdirectories in <see cref="Path"/>, false to only watch entries directly
/// in <see cref="Path"/>.
/// </summary>
bool IncludeSubdirectories { get; set; }
}
public class VirtualWatcherRenamedEventArgs : VirtualWatcherChangedArgs
{
public VirtualWatcherRenamedEventArgs(IVirtualFilesystem fs,WatcherChangeTypes changeTypes,UnixPath newPath,UnixPath oldPath) : base(fs,changeTypes,newPath)
{
OldFullPath = oldPath;
OldName = oldPath.Name;
}
public UnixPath OldFullPath {get;}
public string OldName {get;}
}
public class VirtualWatcherChangedArgs : EventArgs
{
public VirtualWatcherChangedArgs(IVirtualFilesystem fs,WatcherChangeTypes changeTypes,UnixPath path)
{
FullPath=path;
Name = path.Name;
Filesystem = fs;
ChangeType = changeTypes;
}
public IVirtualFilesystem Filesystem {get;}
public WatcherChangeTypes ChangeType {get;}
public UnixPath FullPath { get; }
public string Name {get;}
}
/*
public class UnixPathList : UnixPath, IReadOnlyCollection<UnixPath>
{
private string tostr(int i,UnixPath[] paths)
{
if(i == 0)
{
return paths[0].ToString();
}
else
{
var p = paths[i];
if(!string.IsNullOrWhiteSpace(p._scheme))
{
return $"{p._scheme}://[{tostr(i-1,paths)}]{p._path}";
}
else
{
return $"[{tostr(i - 1, paths)}]{p._path}";
}
}
}
private bool LastIsRoot
{
get
{
if (Count > 0)
{
return _paths[_paths.Length - 1].IsRoot;
}
return false;
}
}
public UnixPathList ParentPL
{
get
{
if (LastIsRoot)
{
List<UnixPath> paths = new List<UnixPath>();
for (int i = 0; i < Count - 2; i++)
{
paths.Add(new UnixPath(this[i]));
}
if (Count > 1)
{
paths.Add(this[Count - 2].Parent);
}
return new UnixPathList(paths);
}
else
{
List<UnixPath> paths = new List<UnixPath>();
for (int i = 0; i < Count - 1; i++)
{
paths.Add(new UnixPath(this[i]));
}
if (Count > 0)
{
paths.Add(this[Count - 1].Parent);
}
return new UnixPathList(paths);
}
}
}
UnixPath[] _paths;
public UnixPathList(params UnixPath[] paths)
{
_paths = paths;
if (_paths.Length > 0)
{
_path = _paths[0]._path;
_parts = _paths[0]._parts;
_scheme = _paths[0]._scheme;
}
}
public UnixPathList(IEnumerable<UnixPath> paths) : this(paths.ToArray())
{
}
public static UnixPathList Parse(string path)
{
List<UnixPath> paths = new List<UnixPath>();
Parse(path, paths);
return new UnixPathList(paths);
}
private static void Parse(string path, List<UnixPath> paths)
{
string scheme = "";
if (path.Contains("://"))
{
var res = path.Split(new string[] { "://" }, 2, StringSplitOptions.None);
scheme = res[0] + "://";
path = res[1];
}
if (path[0] == '[')
{
int br = 1;
int i = 1;
for (; i < path.Length; i++)
{
if (path[i] == '[') br++;
if (path[i] == ']') br--;
if (br <= 0) break;
}
Parse(path.Substring(1, i - 1), paths);
paths.Add(scheme + path.Substring(i + 1));
}
else
{
paths.Add(scheme + path);
}
}
public IEnumerator<UnixPath> GetEnumerator()
{
return _G().GetEnumerator();
}
private IEnumerable<UnixPath> _G()
{
foreach(UnixPath p in _paths)
{
yield return p;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return _G().GetEnumerator();
}
public UnixPath this[int i]
{
get
{
return _paths[i];
}
set
{
_paths[i] = value;
}
}
public int Count { get { return _paths.Length; } }
public override string AsText
{
get
{
if (Count < 2)
{
return ToString();
}
else
{
return tostr(Count-1,_paths);
}
}
}
private string GetFs()
{
return "";
}
}*/
public class Special
{
public static UnixPath CurDir {get{return UnixPath.FromLocal(Environment.CurrentDirectory);} set{Environment.CurrentDirectory = value.ToLocal();}}
public static UnixPath Root {get;} = new UnixPath();
public static UnixPath Home {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.UserProfile);}}
public static UnixPath Videos {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.MyVideos);}}
public static UnixPath Pictures {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.MyPictures);}}
public static UnixPath Documents {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.MyDocuments);}}
public static UnixPath LocalAppData {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.LocalApplicationData);}}
public static UnixPath RoamingAppData {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.ApplicationData);}}
public static UnixPath Music {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.MyMusic);}}
public static UnixPath DesktopFolder {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.DesktopDirectory);}}
public static UnixPath PublicVideos {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonVideos);}}
public static UnixPath PublicPictures {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonPictures);}}
public static UnixPath PublicDocuments {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonDocuments);}}
public static UnixPath PublicAppData {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonApplicationData);}}
public static UnixPath PublicStart {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonStartMenu);}}
public static UnixPath PublicTemplates {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonTemplates);}}
public static UnixPath Start {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.StartMenu);}}
public static UnixPath Templates {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.Templates);}}
public static UnixPath ProgramFiles {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.ProgramFiles);}}
public static UnixPath ProgramFilesX86 {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.ProgramFilesX86);}}
public static UnixPath Programs {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.Programs);}}
public static UnixPath CommonProgramFiles {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonProgramFiles);}}
public static UnixPath CommonProgramFilesX86 {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonProgramFilesX86);}}
public static UnixPath CommonPrograms {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonPrograms);}}
public static UnixPath PublicDesktopFolder {get {return UnixPath.FromSpecialDirectory(Environment.SpecialFolder.CommonDesktopDirectory);}}
}
public class UnixPath
{
public string ToLocal()
{
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
{
// /mnt/driveLetter/
if(Parts[0] != "mnt")
{
return "";
}else{
List<string> p = new List<string>();
for(int i = 0;i<Parts.Length;i++)
{
if(i == 0)
{
p.Add($"{Parts[i].ToUpper()}:");
}else{
p.Add(Parts[i]);
}
}
return string.Join("\\",p);
}
}
else
{
return Path;
}
}
public static UnixPath FromSpecialDirectory(Environment.SpecialFolder specialFolder)
{
return UnixPath.FromLocal(Environment.GetFolderPath(specialFolder));
}
public static UnixPath FromLocal(string path)
{
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
{
string[] p = path.Split(new char[]{':'},2,StringSplitOptions.None);
List<string> paths=new List<string>();
paths.Add("mnt");
paths.Add(p[0].ToLower());
foreach(var path0 in p[1].Split('\\'))
{
paths.Add(path0);
}
return new UnixPath(paths);
}
else
{
return path;
}
}
public UnixPath()
{
_path = "/";
_parts = new string[0];
}
public UnixPath(IEnumerable<string> pathParts)
{
UnixPath path = new UnixPath();
foreach (var item in pathParts)
{
path /= new UnixPath(item);
}
_parts = path._parts;
path = path._path;
}
public UnixPath(UnixPath path1, UnixPath path2)
{
List<string> pathParts = new List<string>();
pathParts.AddRange(path1.Parts);
pathParts.AddRange(path2.Parts);
SetPath(pathParts);
}
private void SetPath(IEnumerable<string> p)
{
_parts = p.ToArray();
StringBuilder pa = new StringBuilder();
for (int i = 0; i < _parts.Length; i++)
{
pa.Append($"/{_parts[i]}");
}
if(pa.Length > 0)
_path = pa.ToString();
else
_path = "/";
}
public UnixPath(UnixPath path1)
{
_parts = path1._parts.ToArray();
_path = path1._path;
}
public UnixPath(params string[] pathParts) : this((IEnumerable<string>)pathParts)
{
}
public UnixPath(UnixPath path, params string[] pathParts) : this(path, new UnixPath(pathParts))
{
}
public UnixPath(string path)
{
SetPath(path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries));
}
public static DirectoryPointer operator/(IVirtualFilesystem fs,UnixPath path)
{
return new DirectoryPointer(fs,path);
}
public static UnixPath operator /(UnixPath path, string path2)
{
return new UnixPath(path, path2);
}
public static UnixPath operator /(UnixPath path1, UnixPath path2)
{
return new UnixPath(
path1, path2
);
}
public static UnixPath operator +(UnixPath path1, string path2)
{
return path1 + new UnixPath(path2);
}
public static UnixPath operator +(UnixPath path1, UnixPath path2)
{
List<string> p = new List<string>();
StringBuilder b = new StringBuilder();
for (int i = 0; i < path1._parts.Length - 1; i++)
{
p.Add(path1._parts[i]);
}
if (path1._parts.Length - 1 >= 0)
{
b.Append(path1._parts[path1._parts.Length - 1]);
}
if (path2._parts.Length > 0)
{
b.Append(path2._parts[0]);
}
if (b.Length > 0)
{
p.Add(b.ToString());
}
for (int i = 1; i < path2._parts.Length; i++)
{
p.Add(path2._parts[i]);
}
var path = new UnixPath();
path.SetPath(p);
return path;
}
public static implicit operator UnixPath(string path)
{
return new UnixPath(path);
}
public static implicit operator UnixPath(string[] path)
{
return new UnixPath((IEnumerable<string>)path);
}
public bool MyPathEquals(UnixPath path)
{
if(path.Parts.Length != Parts.Length) return false;
for(int i = 0;i<Parts.Length;i++)
{
if(Parts[i] != path.Parts[i]) return false;
}
return true;
}
internal string _path;
public string Path { get { return _path; } }
public string Name { get { if (_parts.Length == 0) return ""; return _parts[_parts.Length - 1]; } set{
if(_parts.Length > 0) _parts[_parts.Length-1] = value;
} }
public bool IsRoot
{
get
{
return _parts.Length == 0;
}
}
public bool ParentIsRoot
{
get
{
return _parts.Length <= 1;
}
}
public UnixPath Parent
{
get
{
var p = new UnixPath();
if (!ParentIsRoot)
{
p.SetPath(_parts.Take(_parts.Length - 1));
}
return p;
}
}
internal string[] _parts;
public string[] Parts { get { return _parts; } }
public virtual string AsText
{
get { return ToString(); }
}
public override string ToString()
{
return _path;
}
}
}