DTLib/DTLib/Filesystem/IOPath.cs
2024-09-26 03:09:28 +05:00

173 lines
8.3 KiB
C#

#if NETSTANDARD2_1 || NET6_0_OR_GREATER
#define USE_SPAN
#endif
using System.Runtime.CompilerServices;
namespace DTLib.Filesystem;
/// <summary>
/// represents filesystem path with proper dir separators and without trailing separator
/// </summary>
public readonly struct IOPath
{
public readonly string Str;
public IOPath(char[] path, bool separatorsFixed=false)
{
Str = separatorsFixed ? new string(path) : FixSeparators(path);
}
public IOPath(string path, bool separatorsFixed=false)
{
if (path.IsNullOrEmpty())
throw new Exception("path is null or empty");
Str = separatorsFixed ? path : FixSeparators(path.ToCharArray());
}
static string FixSeparators(char[] path)
{
int length = path.Length;
if (path[length-1] == Path.Sep || path[length-1] == Path.NotSep)
length--; // removing trailing sep
char[] fixed_path = new char[length];
for (int i = 0; i < length; i++)
{
if (path[i] == Path.NotSep)
fixed_path[i] = Path.Sep;
else fixed_path[i] = path[i];
}
return new string(fixed_path);
}
public static IOPath[] ArrayCast(string[] a, bool separatorsFixed=false)
{
IOPath[] b = new IOPath[a.Length];
for (int i = 0; i < a.Length; i++)
b[i] = new IOPath(a[i], separatorsFixed);
return b;
}
public static IOPath[] ListCast(IList<string> a, bool separatorsFixed=false)
{
IOPath[] b = new IOPath[a.Count];
for (int i = 0; i < a.Count; i++)
b[i] = new IOPath(a[i], separatorsFixed);
return b;
}
// public static IOPath operator +(IOPath a, IOPath b) => Path.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)
{
if (obj is null) return false;
return Str == obj.ToString();
}
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);
[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);
}