mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Change most things to new byte strings, introduce new ResourceLoader and Logger fully.
This commit is contained in:
parent
5d77cd5514
commit
f5fccb0235
55 changed files with 2681 additions and 2730 deletions
|
|
@ -1,17 +1,21 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.Util;
|
||||
|
||||
namespace Penumbra.GameData.ByteString;
|
||||
|
||||
[JsonConverter( typeof( FullPathConverter ) )]
|
||||
public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
||||
{
|
||||
public readonly string FullName;
|
||||
public readonly Utf8String InternalName;
|
||||
public readonly ulong Crc64;
|
||||
|
||||
public static readonly FullPath Empty = new(string.Empty);
|
||||
|
||||
public FullPath( DirectoryInfo baseDir, NewRelPath relPath )
|
||||
public FullPath( DirectoryInfo baseDir, Utf8RelPath relPath )
|
||||
: this( Path.Combine( baseDir.FullName, relPath.ToString() ) )
|
||||
{ }
|
||||
|
||||
|
|
@ -19,10 +23,11 @@ public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
|||
: this( file.FullName )
|
||||
{ }
|
||||
|
||||
|
||||
public FullPath( string s )
|
||||
{
|
||||
FullName = s;
|
||||
InternalName = Utf8String.FromString( FullName, out var name, true ) ? name : Utf8String.Empty;
|
||||
InternalName = Utf8String.FromString( FullName, out var name, true ) ? name.Replace( ( byte )'\\', ( byte )'/' ) : Utf8String.Empty;
|
||||
Crc64 = Functions.ComputeCrc64( InternalName.Span );
|
||||
}
|
||||
|
||||
|
|
@ -35,9 +40,9 @@ public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
|||
public string Name
|
||||
=> Path.GetFileName( FullName );
|
||||
|
||||
public bool ToGamePath( DirectoryInfo dir, out NewGamePath path )
|
||||
public bool ToGamePath( DirectoryInfo dir, out Utf8GamePath path )
|
||||
{
|
||||
path = NewGamePath.Empty;
|
||||
path = Utf8GamePath.Empty;
|
||||
if( !InternalName.IsAscii || !FullName.StartsWith( dir.FullName ) )
|
||||
{
|
||||
return false;
|
||||
|
|
@ -45,13 +50,13 @@ public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
|||
|
||||
var substring = InternalName.Substring( dir.FullName.Length + 1 );
|
||||
|
||||
path = new NewGamePath( substring.Replace( ( byte )'\\', ( byte )'/' ) );
|
||||
path = new Utf8GamePath( substring );
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ToRelPath( DirectoryInfo dir, out NewRelPath path )
|
||||
public bool ToRelPath( DirectoryInfo dir, out Utf8RelPath path )
|
||||
{
|
||||
path = NewRelPath.Empty;
|
||||
path = Utf8RelPath.Empty;
|
||||
if( !FullName.StartsWith( dir.FullName ) )
|
||||
{
|
||||
return false;
|
||||
|
|
@ -59,7 +64,7 @@ public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
|||
|
||||
var substring = InternalName.Substring( dir.FullName.Length + 1 );
|
||||
|
||||
path = new NewRelPath( substring );
|
||||
path = new Utf8RelPath( substring.Replace( ( byte )'/', ( byte )'\\' ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -88,9 +93,35 @@ public readonly struct FullPath : IComparable, IEquatable< FullPath >
|
|||
return InternalName.Equals( other.InternalName );
|
||||
}
|
||||
|
||||
public bool IsRooted
|
||||
=> new Utf8GamePath( InternalName ).IsRooted();
|
||||
|
||||
public override int GetHashCode()
|
||||
=> InternalName.Crc32;
|
||||
|
||||
public override string ToString()
|
||||
=> FullName;
|
||||
|
||||
public class FullPathConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
=> objectType == typeof( FullPath );
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load( reader ).ToString();
|
||||
return new FullPath( token );
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
=> true;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object? value, JsonSerializer serializer )
|
||||
{
|
||||
if( value is FullPath p )
|
||||
{
|
||||
serializer.Serialize( writer, p.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,21 @@ using System.IO;
|
|||
using Dalamud.Utility;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.Util;
|
||||
|
||||
namespace Penumbra.GameData.ByteString;
|
||||
|
||||
// NewGamePath wrap some additional validity checking around Utf8String,
|
||||
// provide some filesystem helpers, and conversion to Json.
|
||||
[JsonConverter( typeof( NewGamePathConverter ) )]
|
||||
public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< NewGamePath >, IDisposable
|
||||
[JsonConverter( typeof( Utf8GamePathConverter ) )]
|
||||
public readonly struct Utf8GamePath : IEquatable< Utf8GamePath >, IComparable< Utf8GamePath >, IDisposable
|
||||
{
|
||||
public const int MaxGamePathLength = 256;
|
||||
|
||||
public readonly Utf8String Path;
|
||||
public static readonly NewGamePath Empty = new(Utf8String.Empty);
|
||||
public readonly Utf8String Path;
|
||||
public static readonly Utf8GamePath Empty = new(Utf8String.Empty);
|
||||
|
||||
internal NewGamePath( Utf8String s )
|
||||
internal Utf8GamePath( Utf8String s )
|
||||
=> Path = s;
|
||||
|
||||
public int Length
|
||||
|
|
@ -25,16 +26,16 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
public bool IsEmpty
|
||||
=> Path.IsEmpty;
|
||||
|
||||
public NewGamePath ToLower()
|
||||
public Utf8GamePath ToLower()
|
||||
=> new(Path.AsciiToLower());
|
||||
|
||||
public static unsafe bool FromPointer( byte* ptr, out NewGamePath path, bool lower = false )
|
||||
public static unsafe bool FromPointer( byte* ptr, out Utf8GamePath path, bool lower = false )
|
||||
{
|
||||
var utf = new Utf8String( ptr );
|
||||
return ReturnChecked( utf, out path, lower );
|
||||
}
|
||||
|
||||
public static bool FromSpan( ReadOnlySpan< byte > data, out NewGamePath path, bool lower = false )
|
||||
public static bool FromSpan( ReadOnlySpan< byte > data, out Utf8GamePath path, bool lower = false )
|
||||
{
|
||||
var utf = Utf8String.FromSpanUnsafe( data, false, null, null );
|
||||
return ReturnChecked( utf, out path, lower );
|
||||
|
|
@ -43,7 +44,7 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
// Does not check for Forward/Backslashes due to assuming that SE-strings use the correct one.
|
||||
// Does not check for initial slashes either, since they are assumed to be by choice.
|
||||
// Checks for maxlength, ASCII and lowercase.
|
||||
private static bool ReturnChecked( Utf8String utf, out NewGamePath path, bool lower = false )
|
||||
private static bool ReturnChecked( Utf8String utf, out Utf8GamePath path, bool lower = false )
|
||||
{
|
||||
path = Empty;
|
||||
if( !utf.IsAscii || utf.Length > MaxGamePathLength )
|
||||
|
|
@ -51,14 +52,17 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
return false;
|
||||
}
|
||||
|
||||
path = new NewGamePath( lower ? utf.AsciiToLower() : utf );
|
||||
path = new Utf8GamePath( lower ? utf.AsciiToLower() : utf );
|
||||
return true;
|
||||
}
|
||||
|
||||
public NewGamePath Clone()
|
||||
public Utf8GamePath Clone()
|
||||
=> new(Path.Clone());
|
||||
|
||||
public static bool FromString( string? s, out NewGamePath path, bool toLower = false )
|
||||
public static explicit operator Utf8GamePath( string s )
|
||||
=> FromString( s, out var p, true ) ? p : Empty;
|
||||
|
||||
public static bool FromString( string? s, out Utf8GamePath path, bool toLower = false )
|
||||
{
|
||||
path = Empty;
|
||||
if( s.IsNullOrEmpty() )
|
||||
|
|
@ -83,11 +87,11 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
return false;
|
||||
}
|
||||
|
||||
path = new NewGamePath( ascii );
|
||||
path = new Utf8GamePath( ascii );
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool FromFile( FileInfo file, DirectoryInfo baseDir, out NewGamePath path, bool toLower = false )
|
||||
public static bool FromFile( FileInfo file, DirectoryInfo baseDir, out Utf8GamePath path, bool toLower = false )
|
||||
{
|
||||
path = Empty;
|
||||
if( !file.FullName.StartsWith( baseDir.FullName ) )
|
||||
|
|
@ -111,13 +115,13 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
return idx == -1 ? Utf8String.Empty : Path.Substring( idx );
|
||||
}
|
||||
|
||||
public bool Equals( NewGamePath other )
|
||||
public bool Equals( Utf8GamePath other )
|
||||
=> Path.Equals( other.Path );
|
||||
|
||||
public override int GetHashCode()
|
||||
=> Path.GetHashCode();
|
||||
|
||||
public int CompareTo( NewGamePath other )
|
||||
public int CompareTo( Utf8GamePath other )
|
||||
=> Path.CompareTo( other.Path );
|
||||
|
||||
public override string ToString()
|
||||
|
|
@ -132,17 +136,17 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
&& ( Path[ 0 ] >= 'A' && Path[ 0 ] <= 'Z' || Path[ 0 ] >= 'a' && Path[ 0 ] <= 'z' )
|
||||
&& Path[ 1 ] == ':';
|
||||
|
||||
private class NewGamePathConverter : JsonConverter
|
||||
public class Utf8GamePathConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
=> objectType == typeof( NewGamePath );
|
||||
=> objectType == typeof( Utf8GamePath );
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load( reader ).ToString();
|
||||
return FromString( token, out var p, true )
|
||||
? p
|
||||
: throw new JsonException( $"Could not convert \"{token}\" to {nameof( NewGamePath )}." );
|
||||
: throw new JsonException( $"Could not convert \"{token}\" to {nameof( Utf8GamePath )}." );
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
|
|
@ -150,10 +154,13 @@ public readonly struct NewGamePath : IEquatable< NewGamePath >, IComparable< New
|
|||
|
||||
public override void WriteJson( JsonWriter writer, object? value, JsonSerializer serializer )
|
||||
{
|
||||
if( value is NewGamePath p )
|
||||
if( value is Utf8GamePath p )
|
||||
{
|
||||
serializer.Serialize( writer, p.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GamePath ToGamePath()
|
||||
=> GamePath.GenerateUnchecked( ToString() );
|
||||
}
|
||||
|
|
@ -1,23 +1,28 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Dalamud.Utility;
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Penumbra.GameData.ByteString;
|
||||
|
||||
[JsonConverter( typeof( NewRelPathConverter ) )]
|
||||
public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRelPath >, IDisposable
|
||||
[JsonConverter( typeof( Utf8RelPathConverter ) )]
|
||||
public readonly struct Utf8RelPath : IEquatable< Utf8RelPath >, IComparable< Utf8RelPath >, IDisposable
|
||||
{
|
||||
public const int MaxRelPathLength = 250;
|
||||
|
||||
public readonly Utf8String Path;
|
||||
public static readonly NewRelPath Empty = new(Utf8String.Empty);
|
||||
public readonly Utf8String Path;
|
||||
public static readonly Utf8RelPath Empty = new(Utf8String.Empty);
|
||||
|
||||
internal NewRelPath( Utf8String path )
|
||||
internal Utf8RelPath( Utf8String path )
|
||||
=> Path = path;
|
||||
|
||||
public static bool FromString( string? s, out NewRelPath path )
|
||||
|
||||
public static explicit operator Utf8RelPath( string s )
|
||||
=> FromString( s, out var p ) ? p : Empty;
|
||||
|
||||
public static bool FromString( string? s, out Utf8RelPath path )
|
||||
{
|
||||
path = Empty;
|
||||
if( s.IsNullOrEmpty() )
|
||||
|
|
@ -42,11 +47,11 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
return false;
|
||||
}
|
||||
|
||||
path = new NewRelPath( ascii );
|
||||
path = new Utf8RelPath( ascii );
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool FromFile( FileInfo file, DirectoryInfo baseDir, out NewRelPath path )
|
||||
public static bool FromFile( FileInfo file, DirectoryInfo baseDir, out Utf8RelPath path )
|
||||
{
|
||||
path = Empty;
|
||||
if( !file.FullName.StartsWith( baseDir.FullName ) )
|
||||
|
|
@ -58,7 +63,7 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
return FromString( substring, out path );
|
||||
}
|
||||
|
||||
public static bool FromFile( FullPath file, DirectoryInfo baseDir, out NewRelPath path )
|
||||
public static bool FromFile( FullPath file, DirectoryInfo baseDir, out Utf8RelPath path )
|
||||
{
|
||||
path = Empty;
|
||||
if( !file.FullName.StartsWith( baseDir.FullName ) )
|
||||
|
|
@ -70,10 +75,10 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
return FromString( substring, out path );
|
||||
}
|
||||
|
||||
public NewRelPath( NewGamePath gamePath )
|
||||
public Utf8RelPath( Utf8GamePath gamePath )
|
||||
=> Path = gamePath.Path.Replace( ( byte )'/', ( byte )'\\' );
|
||||
|
||||
public unsafe NewGamePath ToGamePath( int skipFolders = 0 )
|
||||
public unsafe Utf8GamePath ToGamePath( int skipFolders = 0 )
|
||||
{
|
||||
var idx = 0;
|
||||
while( skipFolders > 0 )
|
||||
|
|
@ -82,7 +87,7 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
--skipFolders;
|
||||
if( idx <= 0 )
|
||||
{
|
||||
return NewGamePath.Empty;
|
||||
return Utf8GamePath.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,13 +96,13 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
ByteStringFunctions.Replace( ptr, length, ( byte )'\\', ( byte )'/' );
|
||||
ByteStringFunctions.AsciiToLowerInPlace( ptr, length );
|
||||
var utf = new Utf8String().Setup( ptr, length, null, true, true, true, true );
|
||||
return new NewGamePath( utf );
|
||||
return new Utf8GamePath( utf );
|
||||
}
|
||||
|
||||
public int CompareTo( NewRelPath rhs )
|
||||
public int CompareTo( Utf8RelPath rhs )
|
||||
=> Path.CompareTo( rhs.Path );
|
||||
|
||||
public bool Equals( NewRelPath other )
|
||||
public bool Equals( Utf8RelPath other )
|
||||
=> Path.Equals( other.Path );
|
||||
|
||||
public override string ToString()
|
||||
|
|
@ -106,17 +111,17 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
public void Dispose()
|
||||
=> Path.Dispose();
|
||||
|
||||
private class NewRelPathConverter : JsonConverter
|
||||
public class Utf8RelPathConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
=> objectType == typeof( NewRelPath );
|
||||
=> objectType == typeof( Utf8RelPath );
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load( reader ).ToString();
|
||||
return FromString( token, out var p )
|
||||
? p
|
||||
: throw new JsonException( $"Could not convert \"{token}\" to {nameof( NewRelPath )}." );
|
||||
: throw new JsonException( $"Could not convert \"{token}\" to {nameof( Utf8RelPath )}." );
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
|
|
@ -124,7 +129,7 @@ public readonly struct NewRelPath : IEquatable< NewRelPath >, IComparable< NewRe
|
|||
|
||||
public override void WriteJson( JsonWriter writer, object? value, JsonSerializer serializer )
|
||||
{
|
||||
if( value is NewRelPath p )
|
||||
if( value is Utf8RelPath p )
|
||||
{
|
||||
serializer.Serialize( writer, p.ToString() );
|
||||
}
|
||||
|
|
@ -75,6 +75,19 @@ public sealed unsafe partial class Utf8String : IEquatable< Utf8String >, ICompa
|
|||
return ByteStringFunctions.AsciiCaselessCompare( _path, Length, other._path, other.Length );
|
||||
}
|
||||
|
||||
public bool StartsWith( Utf8String other )
|
||||
{
|
||||
var otherLength = other.Length;
|
||||
return otherLength <= Length && ByteStringFunctions.Equals( other.Path, otherLength, Path, otherLength );
|
||||
}
|
||||
|
||||
public bool EndsWith( Utf8String other )
|
||||
{
|
||||
var otherLength = other.Length;
|
||||
var offset = Length - otherLength;
|
||||
return offset >= 0 && ByteStringFunctions.Equals( other.Path, otherLength, Path + offset, otherLength );
|
||||
}
|
||||
|
||||
public bool StartsWith( params char[] chars )
|
||||
{
|
||||
if( chars.Length > Length )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue