mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-30 21:20:29 -05:00
Add ITrashIntrospection, impl on PKM classes
new api allows for checking for trash byte metadata, makes it much easier to write a verifier now
This commit is contained in:
@@ -319,4 +319,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter4.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter4.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter4.Terminator);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter4.Terminator);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -237,4 +237,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter3GC.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter3GC.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter3GC.TerminatorBigEndian);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter3GC.TerminatorBigEndian);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -432,6 +432,11 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Revises the Handler details of a <see cref="PKM"/> to match the current <see cref="ITrainerInfo"/>.
|
||||
|
||||
@@ -738,4 +738,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -593,4 +593,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -141,4 +141,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -254,6 +254,11 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter1.LoadString(data, destBuffer, Japanese);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter1.SetString(destBuffer, value, maxLength, Japanese, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter4.Terminator);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter4.Terminator);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a checksum over all the entity's data using a single list to wrap all components.
|
||||
|
||||
@@ -279,6 +279,11 @@ public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, i
|
||||
return StringConverter2KOR.SetString(destBuffer, value, maxLength, option);
|
||||
return StringConverter2.SetString(destBuffer, value, maxLength, Language, option);
|
||||
}
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> Korean ? StringConverter2KOR.GetTerminatorIndex(data) : TrashBytesGB.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> Korean ? StringConverter2KOR.GetStringLength(data) : TrashBytesGB.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a checksum over all the entity's data using a single list to wrap all components.
|
||||
|
||||
@@ -362,4 +362,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter3.LoadString(data, destBuffer, Language);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter3.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes8.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes8.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 1;
|
||||
}
|
||||
|
||||
@@ -395,4 +395,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter4.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter4.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter4.Terminator);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter4.Terminator);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -572,6 +572,11 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter5.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter5.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter5.Terminator);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter5.Terminator);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
|
||||
/// <inheritdoc cref="G4PKM.CheckKoreanNidoranDPPt"/>
|
||||
/// <remarks> Gen4->Gen5 chars transfer without resetting the name. Still relevant even as PK5. </remarks>
|
||||
|
||||
@@ -531,4 +531,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter6.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter6.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -556,6 +556,11 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter7.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter7.SetString(destBuffer, value, maxLength, Language);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
public enum ResortEventState : byte
|
||||
|
||||
@@ -124,4 +124,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -677,4 +677,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter8.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace PKHeX.Core;
|
||||
/// Object representing a <see cref="PKM"/>'s data and derived properties.
|
||||
/// </summary>
|
||||
[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties | PublicParameterlessConstructor)]
|
||||
public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILangNick, IGameValueLimit, INature, IFatefulEncounter, IStringConverter
|
||||
public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILangNick, IGameValueLimit, INature, IFatefulEncounter, IStringConverter, ITrashIntrospection
|
||||
{
|
||||
/// <summary>
|
||||
/// Valid file extensions that represent <see cref="PKM"/> data, without the leading '.'
|
||||
@@ -151,6 +151,9 @@ private byte[] Write()
|
||||
public abstract string GetString(ReadOnlySpan<byte> data);
|
||||
public abstract int LoadString(ReadOnlySpan<byte> data, Span<char> text);
|
||||
public abstract int SetString(Span<byte> data, ReadOnlySpan<char> text, int length, StringConverterOption option);
|
||||
public abstract int GetStringTerminatorIndex(ReadOnlySpan<byte> data);
|
||||
public abstract int GetStringLength(ReadOnlySpan<byte> data);
|
||||
public abstract int GetBytesPerChar();
|
||||
|
||||
/// <summary>
|
||||
/// The date the Pokémon was met.
|
||||
|
||||
@@ -357,4 +357,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter4.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter4.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter4.Terminator);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter4.Terminator);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
@@ -221,4 +221,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter2.LoadString(data, destBuffer, Language);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter2.SetString(destBuffer, value, maxLength, Language, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytesGB.GetTerminatorIndex(data);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytesGB.GetStringLength(data);
|
||||
public override int GetBytesPerChar() => 1;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,40 @@ public static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
return ctr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of characters in the data.
|
||||
/// </summary>
|
||||
public static int GetStringLength(ReadOnlySpan<byte> data)
|
||||
{
|
||||
int length = 0;
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
byte value = data[i];
|
||||
if (value is TableInvalid or TerminatorCode)
|
||||
break;
|
||||
if (value <= TableMax)
|
||||
i++; // Korean char takes 2 bytes
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the first terminator in the data.
|
||||
/// </summary>
|
||||
public static int GetTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
{
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
byte value = data[i];
|
||||
if (value is TableInvalid or TerminatorCode)
|
||||
return i;
|
||||
if (value <= TableMax)
|
||||
i++; // Korean char takes 2 bytes
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to Generation 1 encoded data.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace PKHeX.Core;
|
||||
/// </summary>
|
||||
public static class StringConverter3GC
|
||||
{
|
||||
private const char TerminatorBigEndian = (char)0; // GC
|
||||
public const char TerminatorBigEndian = (char)0; // GC
|
||||
|
||||
/// <summary>Converts Big Endian encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace PKHeX.Core;
|
||||
/// </summary>
|
||||
public static class StringConverter5
|
||||
{
|
||||
private const char TerminatorFFFF = (char)0xFFFF;
|
||||
public const char Terminator = (char)0xFFFF;
|
||||
|
||||
/// <summary>Converts Generation 5 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
@@ -31,7 +31,7 @@ public static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == TerminatorFFFF)
|
||||
if (value == Terminator)
|
||||
break;
|
||||
result[ctr++] = (char)value;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], TerminatorFFFF);
|
||||
WriteUInt16LittleEndian(destBuffer[count..], Terminator);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
||||
|
||||
10
PKHeX.Core/PKM/Strings/Trash/ITrashIntrospection.cs
Normal file
10
PKHeX.Core/PKM/Strings/Trash/ITrashIntrospection.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public interface ITrashIntrospection
|
||||
{
|
||||
int GetStringTerminatorIndex(ReadOnlySpan<byte> data);
|
||||
int GetStringLength(ReadOnlySpan<byte> data);
|
||||
int GetBytesPerChar();
|
||||
}
|
||||
@@ -16,7 +16,7 @@ public static class TrashBytes
|
||||
/// <returns>Decoded index (char) of the terminator, or max length if not found.</returns>
|
||||
public static int GetStringLength(ReadOnlySpan<byte> buffer, ushort terminator = 0)
|
||||
{
|
||||
int index = FindTerminatorIndex(buffer, terminator);
|
||||
int index = GetTerminatorIndex(buffer, terminator);
|
||||
return index == -1 ? buffer.Length / 2 : index;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public static int GetStringLength(ReadOnlySpan<byte> buffer, ushort terminator =
|
||||
/// <param name="terminator">Terminator character to search for.</param>
|
||||
/// <returns>Decoded index (char) of the terminator, or -1 if not found.</returns>
|
||||
/// <remarks>When used on a raw string, returns the computed length of the string, assuming a terminator is present.</remarks>
|
||||
public static int FindTerminatorIndex(ReadOnlySpan<byte> buffer, ushort terminator = 0)
|
||||
public static int GetTerminatorIndex(ReadOnlySpan<byte> buffer, ushort terminator = 0)
|
||||
{
|
||||
var u16 = MemoryMarshal.Cast<byte, ushort>(buffer);
|
||||
return u16.IndexOf(terminator);
|
||||
|
||||
@@ -10,7 +10,7 @@ public static class TrashBytes8
|
||||
/// <inheritdoc cref="TrashBytes.GetStringLength"/>
|
||||
public static int GetStringLength(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
int index = FindTerminatorIndex(buffer);
|
||||
int index = GetTerminatorIndex(buffer);
|
||||
return index == -1 ? buffer.Length : index;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ public static int GetStringLength(ReadOnlySpan<byte> buffer)
|
||||
/// </summary>
|
||||
/// <param name="buffer">Backing buffer of the string.</param>
|
||||
/// <returns>Index of the terminator, or -1 if not found.</returns>
|
||||
public static int FindTerminatorIndex(ReadOnlySpan<byte> buffer)
|
||||
public static int GetTerminatorIndex(ReadOnlySpan<byte> buffer)
|
||||
=> buffer.IndexOf<byte>(0xFF);
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ public static class TrashBytesGB
|
||||
/// <inheritdoc cref="TrashBytes.GetStringLength"/>
|
||||
public static int GetStringLength(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
int index = FindTerminatorIndex(buffer);
|
||||
int index = GetTerminatorIndex(buffer);
|
||||
return index == -1 ? buffer.Length : index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a 16-bit aligned index of the terminator.
|
||||
/// Returns a 8-bit aligned index of the terminator.
|
||||
/// </summary>
|
||||
/// <param name="buffer">Backing buffer of the string.</param>
|
||||
/// <returns>Index of the terminator, or -1 if not found.</returns>
|
||||
public static int FindTerminatorIndex(ReadOnlySpan<byte> buffer)
|
||||
public static int GetTerminatorIndex(ReadOnlySpan<byte> buffer)
|
||||
=> buffer.IndexOfAny(TerminatorZero, TerminatorCode);
|
||||
}
|
||||
|
||||
@@ -241,4 +241,9 @@ public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||
=> StringConverter3GC.LoadString(data, destBuffer);
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||
=> StringConverter3GC.SetString(destBuffer, value, maxLength, option);
|
||||
public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetTerminatorIndex(data, StringConverter3GC.TerminatorBigEndian);
|
||||
public override int GetStringLength(ReadOnlySpan<byte> data)
|
||||
=> TrashBytes.GetStringLength(data, StringConverter3GC.TerminatorBigEndian);
|
||||
public override int GetBytesPerChar() => 2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user