mirror of
https://github.com/aelurum/AssetStudio.git
synced 2026-11-14 11:18:47 -05:00
Update span extensions
This commit is contained in:
+18
-19
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@@ -1463,7 +1463,6 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static uint GetFormatSize(VertexFormat format)
|
||||
{
|
||||
switch (format)
|
||||
@@ -1493,8 +1492,13 @@ namespace AssetStudio
|
||||
return format >= VertexFormat.UInt8;
|
||||
}
|
||||
|
||||
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
|
||||
public static float[] BytesToFloatArray(ReadOnlySpan<byte> inputBytes, VertexFormat format)
|
||||
{
|
||||
if (format == VertexFormat.Float)
|
||||
{
|
||||
return MemoryMarshal.Cast<byte, float>(inputBytes).ToArray();
|
||||
}
|
||||
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new float[len];
|
||||
@@ -1502,15 +1506,8 @@ namespace AssetStudio
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.Float:
|
||||
#if NET
|
||||
result[i] = BinaryPrimitives.ReadSingleLittleEndian(inputBytes.AsSpan(i * 4));
|
||||
#else
|
||||
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
||||
#endif
|
||||
break;
|
||||
case VertexFormat.Float16:
|
||||
result[i] = (float)HalfHelper.ToHalf(inputBytes, i * 2);
|
||||
result[i] = (float)inputBytes.ReadHalf(i * 2);
|
||||
break;
|
||||
case VertexFormat.UNorm8:
|
||||
result[i] = inputBytes[i] / 255f;
|
||||
@@ -1519,10 +1516,10 @@ namespace AssetStudio
|
||||
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
|
||||
break;
|
||||
case VertexFormat.UNorm16:
|
||||
result[i] = BinaryPrimitives.ReadUInt16LittleEndian(inputBytes.AsSpan(i * 2)) / 65535f;
|
||||
result[i] = inputBytes.ReadUInt16(i * 2) / 65535f;
|
||||
break;
|
||||
case VertexFormat.SNorm16:
|
||||
result[i] = Math.Max(BinaryPrimitives.ReadInt16LittleEndian(inputBytes.AsSpan(i * 2)) / 32767f, -1f);
|
||||
result[i] = Math.Max(inputBytes.ReadInt16(i * 2) / 32767f, -1f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1531,6 +1528,11 @@ namespace AssetStudio
|
||||
|
||||
public static int[] BytesToIntArray(ReadOnlySpan<byte> inputBytes, VertexFormat format)
|
||||
{
|
||||
if (format == VertexFormat.SInt32)
|
||||
{
|
||||
return MemoryMarshal.Cast<byte, int>(inputBytes).ToArray();
|
||||
}
|
||||
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new int[len];
|
||||
@@ -1543,16 +1545,13 @@ namespace AssetStudio
|
||||
result[i] = inputBytes[i];
|
||||
break;
|
||||
case VertexFormat.UInt16:
|
||||
result[i] = BinaryPrimitives.ReadUInt16LittleEndian(inputBytes.Slice(i * 2));
|
||||
result[i] = inputBytes.ReadUInt16(i * 2);
|
||||
break;
|
||||
case VertexFormat.SInt16:
|
||||
result[i] = BinaryPrimitives.ReadInt16LittleEndian(inputBytes.Slice(i * 2));
|
||||
result[i] = inputBytes.ReadInt16(i * 2);
|
||||
break;
|
||||
case VertexFormat.UInt32:
|
||||
result[i] = (int)BinaryPrimitives.ReadUInt32LittleEndian(inputBytes.Slice(i * 4));
|
||||
break;
|
||||
case VertexFormat.SInt32:
|
||||
result[i] = BinaryPrimitives.ReadInt32LittleEndian(inputBytes.Slice(i * 4));
|
||||
result[i] = (int)inputBytes.ReadUInt32(i * 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class EndianSpanReader
|
||||
{
|
||||
public static uint ReadUInt32(this Span<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return ReadUInt32((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static uint ReadUInt32(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static long ReadUInt16(this Span<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return ReadUInt16((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static uint ReadUInt16(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadUInt16BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static long ReadInt64(this Span<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return ReadInt64((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static long ReadInt64(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static float ReadSingle(this Span<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return ReadSingle((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
var bytes = data.Slice(start, 4).ToArray();
|
||||
if ((isBigEndian && BitConverter.IsLittleEndian) || (!isBigEndian && !BitConverter.IsLittleEndian))
|
||||
bytes.AsSpan().Reverse();
|
||||
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
#else
|
||||
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadSingleBigEndian(data[start..])
|
||||
: BinaryPrimitives.ReadSingleLittleEndian(data[start..]);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static string ReadStringToNull(this Span<byte> data, int maxLength = 32767)
|
||||
{
|
||||
return ReadStringToNull((ReadOnlySpan<byte>)data, maxLength);
|
||||
}
|
||||
|
||||
public static string ReadStringToNull(this ReadOnlySpan<byte> data, int maxLength = 32767)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[maxLength];
|
||||
var count = 0;
|
||||
while (count != data.Length && count < maxLength)
|
||||
{
|
||||
var b = data[count];
|
||||
if (b == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes[count] = b;
|
||||
count++;
|
||||
}
|
||||
bytes = bytes.Slice(0, count);
|
||||
#if NETFRAMEWORK
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
#else
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class SpanExtensions
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
private static readonly byte[] Buff = new byte[4];
|
||||
#endif
|
||||
|
||||
public static ushort ReadUInt16(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadUInt16((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static ushort ReadUInt16(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadUInt16BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static short ReadInt16(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadInt16((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static short ReadInt16(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadInt16BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static uint ReadUInt32(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadUInt32((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static uint ReadUInt32(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static int ReadInt32(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadInt32((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static int ReadInt32(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadInt32BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static long ReadInt64(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadInt64((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static long ReadInt64(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static Half ReadHalf(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadHalf((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
public static float ReadSingle(this Span<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return ReadSingle((ReadOnlySpan<byte>)data, start, isBigEndian);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Half ReadHalf(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? throw new NotImplementedException()
|
||||
: HalfHelper.ToHalf((ushort)BinaryPrimitives.ReadInt16LittleEndian(data.Slice(start)));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float ReadSingle(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
data = data.Slice(start, 4);
|
||||
if ((isBigEndian && BitConverter.IsLittleEndian) || (!isBigEndian && !BitConverter.IsLittleEndian))
|
||||
(Buff[0], Buff[1], Buff[2], Buff[3]) = (data[3], data[2], data[1], data[0]);
|
||||
else
|
||||
(Buff[0], Buff[1], Buff[2], Buff[3]) = (data[0], data[1], data[2], data[3]);
|
||||
|
||||
return BitConverter.ToSingle(Buff, 0);
|
||||
}
|
||||
#else
|
||||
public static Half ReadHalf(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadHalfBigEndian(data.Slice(start))
|
||||
: BinaryPrimitives.ReadHalfLittleEndian(data.Slice(start));
|
||||
}
|
||||
|
||||
public static float ReadSingle(this ReadOnlySpan<byte> data, int start = 0, bool isBigEndian = false)
|
||||
{
|
||||
return isBigEndian
|
||||
? BinaryPrimitives.ReadSingleBigEndian(data[start..])
|
||||
: BinaryPrimitives.ReadSingleLittleEndian(data[start..]);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static string ReadStringToNull(this Span<byte> data, int start = 0, int maxLength = 32767)
|
||||
{
|
||||
return ReadStringToNull((ReadOnlySpan<byte>)data, start, maxLength);
|
||||
}
|
||||
|
||||
public static string ReadStringToNull(this ReadOnlySpan<byte> data, int start = 0, int maxLength = 32767)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[maxLength];
|
||||
data = data.Slice(start);
|
||||
var count = 0;
|
||||
while (count != data.Length && count < maxLength)
|
||||
{
|
||||
var b = data[count];
|
||||
if (b == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes[count] = b;
|
||||
count++;
|
||||
}
|
||||
bytes = bytes.Slice(0, count);
|
||||
#if NETFRAMEWORK
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
#else
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace AssetStudio
|
||||
var dataLen = Read(headerBuff, 0, headerBuffLen);
|
||||
Position = 0;
|
||||
|
||||
var signature = buff.ReadStringToNull(20);
|
||||
var signature = buff.ReadStringToNull(maxLength: 20);
|
||||
switch (signature)
|
||||
{
|
||||
case "UnityWeb":
|
||||
|
||||
@@ -416,7 +416,7 @@ namespace AssetStudio
|
||||
{
|
||||
buff[i] = 0;
|
||||
buff[i + 1] = 0;
|
||||
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i / 2) * 255f);
|
||||
buff[i + 2] = (byte)MathF.Round((float)image_data.ReadHalf(i / 2) * 255f);
|
||||
buff[i + 3] = 255;
|
||||
}
|
||||
return true;
|
||||
@@ -427,8 +427,8 @@ namespace AssetStudio
|
||||
for (var i = 0; i < outPutDataSize; i += 4)
|
||||
{
|
||||
buff[i] = 0;
|
||||
buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i + 2) * 255f);
|
||||
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i) * 255f);
|
||||
buff[i + 1] = (byte)MathF.Round((float)image_data.ReadHalf(i + 2) * 255f);
|
||||
buff[i + 2] = (byte)MathF.Round((float)image_data.ReadHalf(i) * 255f);
|
||||
buff[i + 3] = 255;
|
||||
}
|
||||
return true;
|
||||
@@ -438,10 +438,10 @@ namespace AssetStudio
|
||||
{
|
||||
for (var i = 0; i < outPutDataSize; i += 4)
|
||||
{
|
||||
buff[i] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 4) * 255f);
|
||||
buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 2) * 255f);
|
||||
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2) * 255f);
|
||||
buff[i + 3] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 6) * 255f);
|
||||
buff[i] = (byte)MathF.Round((float)image_data.ReadHalf(i * 2 + 4) * 255f);
|
||||
buff[i + 1] = (byte)MathF.Round((float)image_data.ReadHalf(i * 2 + 2) * 255f);
|
||||
buff[i + 2] = (byte)MathF.Round((float)image_data.ReadHalf(i * 2) * 255f);
|
||||
buff[i + 3] = (byte)MathF.Round((float)image_data.ReadHalf(i * 2 + 6) * 255f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user