From b502c6ac8a1407597be782ad64595144f5bb2e27 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 22 Feb 2021 14:51:05 +0100 Subject: [PATCH] Added GamePath and RelPath --- Penumbra/Util/PenumbraPath.cs | 136 ++++++++++++++++++++++++ Penumbra/Util/SingleOrArrayConverter.cs | 13 ++- 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 Penumbra/Util/PenumbraPath.cs diff --git a/Penumbra/Util/PenumbraPath.cs b/Penumbra/Util/PenumbraPath.cs new file mode 100644 index 00000000..2e00f3f2 --- /dev/null +++ b/Penumbra/Util/PenumbraPath.cs @@ -0,0 +1,136 @@ +using System; +using System.IO; + +namespace Penumbra.Util +{ + public readonly struct RelPath : IComparable + { + public const int MaxRelPathLength = 256; + + private readonly string _path; + + private RelPath( string path, bool _ ) + => _path = path; + + private RelPath( string? path ) + { + if( path != null && path.Length < MaxRelPathLength ) + { + _path = Trim( ReplaceSlash( path ) ); + } + else + { + _path = ""; + } + } + + public RelPath( FileInfo file, DirectoryInfo baseDir ) + => _path = CheckPre( file, baseDir ) ? Trim( Substring( file, baseDir ) ) : ""; + + public RelPath( GamePath gamePath ) + => _path = gamePath ? ReplaceSlash( gamePath ) : ""; + + private static bool CheckPre( FileInfo file, DirectoryInfo baseDir ) + => file.FullName.StartsWith( baseDir.FullName ) && file.FullName.Length < MaxRelPathLength; + + private static string Substring( FileInfo file, DirectoryInfo baseDir ) + => file.FullName.Substring( baseDir.FullName.Length ); + + private static string ReplaceSlash( string path ) + => path.Replace( '/', '\\' ); + + private static string Trim( string path ) + => path.TrimStart( '\\' ); + + public static implicit operator bool( RelPath relPath ) + => relPath._path.Length > 0; + + public static implicit operator string( RelPath relPath ) + => relPath._path; + + public static explicit operator RelPath( string relPath ) + => new( relPath ); + + public int CompareTo( object rhs ) + { + return rhs switch + { + string => string.Compare( _path, _path, StringComparison.InvariantCulture ), + RelPath path => string.Compare( _path, path._path, StringComparison.InvariantCulture ), + _ => -1 + }; + } + + public override string ToString() + => _path; + } + + public readonly struct GamePath : IComparable + { + public const int MaxGamePathLength = 256; + + private readonly string _path; + + private GamePath( string path, bool _ ) + => _path = path; + + public GamePath( string? path ) + { + if( path != null && path.Length < MaxGamePathLength ) + { + _path = Lower( Trim( ReplaceSlash( path ) ) ); + } + else + { + _path = ""; + } + } + + public GamePath( FileInfo file, DirectoryInfo baseDir ) + => _path = CheckPre( file, baseDir ) ? Lower( Trim( ReplaceSlash( Substring( file, baseDir ) ) ) ) : ""; + + public GamePath( RelPath relPath ) + => _path = relPath ? Lower( ReplaceSlash( relPath ) ) : ""; + + private static bool CheckPre( FileInfo file, DirectoryInfo baseDir ) + => file.FullName.StartsWith( baseDir.FullName ) && file.FullName.Length < MaxGamePathLength; + + private static string Substring( FileInfo file, DirectoryInfo baseDir ) + => file.FullName.Substring( baseDir.FullName.Length ); + + private static string ReplaceSlash( string path ) + => path.Replace( '\\', '/' ); + + private static string Trim( string path ) + => path.TrimStart( '/' ); + + private static string Lower( string path ) + => path.ToLowerInvariant(); + + public static GamePath GenerateUnchecked( string path ) + => new( path, true ); + + public static implicit operator bool( GamePath gamePath ) + => gamePath._path.Length > 0; + + public static implicit operator string( GamePath gamePath ) + => gamePath._path; + + public static explicit operator GamePath( string gamePath ) + => new( gamePath ); + + + public int CompareTo( object rhs ) + { + return rhs switch + { + string path => string.Compare( _path, path, StringComparison.InvariantCulture ), + GamePath path => string.Compare( _path, path._path, StringComparison.InvariantCulture ), + _ => -1 + }; + } + + public override string ToString() + => _path; + } +} \ No newline at end of file diff --git a/Penumbra/Util/SingleOrArrayConverter.cs b/Penumbra/Util/SingleOrArrayConverter.cs index 638e4da0..bb6799ba 100644 --- a/Penumbra/Util/SingleOrArrayConverter.cs +++ b/Penumbra/Util/SingleOrArrayConverter.cs @@ -24,11 +24,20 @@ namespace Penumbra.Util : new HashSet< T >(); } - public override bool CanWrite => false; + public override bool CanWrite => true; public override void WriteJson( JsonWriter writer, object? value, JsonSerializer serializer ) { - throw new NotImplementedException(); + writer.WriteStartArray(); + if( value != null ) + { + var v = ( HashSet< T > )value; + foreach( var val in v ) + { + serializer.Serialize( writer, val?.ToString() ); + } + } + writer.WriteEndArray(); } } } \ No newline at end of file