1
0
mirror of synced 2024-12-04 20:08:00 +01:00
Switch-Toolbox/Switch_Toolbox_Library/IO/Extensions/IOExtensions.cs

148 lines
5.4 KiB
C#
Raw Normal View History

2019-05-28 22:11:40 +02:00
using System;
using System.Collections.Generic;
2019-06-11 02:54:23 +02:00
using System.Text;
using System.IO;
2019-05-28 22:11:40 +02:00
using System.Threading.Tasks;
using System.Text.RegularExpressions;
2019-07-24 21:10:05 +02:00
using Toolbox.Library.Security.Cryptography;
using System.Runtime.InteropServices;
using Syroot.BinaryData;
using System.Linq;
2019-05-28 22:11:40 +02:00
namespace Toolbox.Library.IO
2019-05-28 22:11:40 +02:00
{
public static class IOExtensions
{
//From https://github.com/IcySon55/Kuriimu/blob/master/src/Kontract/IO/Extensions.cs
//Read
public static unsafe T BytesToStruct<T>(this byte[] buffer, bool isBigEndian = false, int offset = 0)
{
if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));
AdjustBigEndianByteOrder(typeof(T), buffer, isBigEndian);
fixed (byte* pBuffer = buffer)
return Marshal.PtrToStructure<T>((IntPtr)pBuffer + offset);
}
// Write
public static unsafe byte[] StructToBytes<T>(this T item, bool isBigEndian)
{
var buffer = new byte[Marshal.SizeOf(typeof(T))];
fixed (byte* pBuffer = buffer)
Marshal.StructureToPtr(item, (IntPtr)pBuffer, false);
AdjustBigEndianByteOrder(typeof(T), buffer, isBigEndian);
return buffer;
}
//Adjust byte order for big endian
private static void AdjustBigEndianByteOrder(Type type, byte[] buffer, bool isBigEndian, int startOffset = 0)
{
if (!isBigEndian)
return;
if (type.IsPrimitive)
{
if (type == typeof(short) || type == typeof(ushort) ||
type == typeof(int) || type == typeof(uint) ||
type == typeof(long) || type == typeof(ulong))
{
Array.Reverse(buffer);
return;
}
}
foreach (var field in type.GetFields())
{
var fieldType = field.FieldType;
// Ignore static fields
if (field.IsStatic) continue;
if (fieldType.BaseType == typeof(Enum) && fieldType != typeof(ByteOrder))
fieldType = fieldType.GetFields()[0].FieldType;
// Swap bytes only for the following types (incomplete just like BinaryReaderX is)
if (fieldType == typeof(short) || fieldType == typeof(ushort) ||
fieldType == typeof(int) || fieldType == typeof(uint) ||
fieldType == typeof(long) || fieldType == typeof(ulong))
{
var offset = Marshal.OffsetOf(type, field.Name).ToInt32();
// Enums
if (fieldType.IsEnum)
fieldType = Enum.GetUnderlyingType(fieldType);
// Check for sub-fields to recurse if necessary
var subFields = fieldType.GetFields().Where(subField => subField.IsStatic == false).ToArray();
var effectiveOffset = startOffset + offset;
if (subFields.Length == 0)
Array.Reverse(buffer, effectiveOffset, Marshal.SizeOf(fieldType));
else
AdjustBigEndianByteOrder(fieldType, buffer, isBigEndian, effectiveOffset);
}
}
}
2019-06-01 15:49:33 +02:00
//https://github.com/exelix11/EditorCore/blob/872d210f85ec0409f8a6ac3a12fc162aaf4cd90c/EditorCoreCommon/CustomClasses.cs#L367
public static bool Matches(this byte[] arr, string magic) =>
arr.Matches(0, magic.ToCharArray());
2019-06-01 16:23:06 +02:00
public static bool Matches(this byte[] arr, uint magic) =>
arr.Matches(0, BitConverter.GetBytes(magic));
public static bool Matches(this byte[] arr, uint startIndex, params byte[] magic)
{
if (arr.Length < magic.Length + startIndex) return false;
for (uint i = 0; i < magic.Length; i++)
{
if (arr[i + startIndex] != magic[i]) return false;
}
return true;
}
2019-06-01 15:49:33 +02:00
2019-06-11 02:54:23 +02:00
public static byte[] ToByteArray(this string str, int length)
{
return Encoding.ASCII.GetBytes(str.PadRight(length, ' '));
}
public static uint EncodeCrc32(this string str)
{
return Crc32.Compute(str);
}
2019-06-01 15:49:33 +02:00
public static bool Matches(this byte[] arr, uint startIndex, params char[] magic)
{
if (arr.Length < magic.Length + startIndex) return false;
for (uint i = 0; i < magic.Length; i++)
{
if (arr[i + startIndex] != magic[i]) return false;
}
return true;
}
2019-05-28 22:11:40 +02:00
public static uint Reverse(this uint x)
{
// swap adjacent 16-bit blocks
x = (x >> 16) | (x << 16);
// swap adjacent 8-bit blocks
return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8);
}
2019-05-28 22:55:17 +02:00
//https://stackoverflow.com/questions/2230826/remove-invalid-disallowed-bad-characters-from-filename-or-directory-folder/12800424#12800424
public static string RemoveIllegaleFileNameCharacters(this string str)
{
2019-05-28 22:55:17 +02:00
return string.Join("_", str.Split(Path.GetInvalidFileNameChars()));
}
2019-05-28 22:55:17 +02:00
public static string RemoveIllegaleFolderNameCharacters(this string str)
{
return string.Join("_", str.Split(Path.GetInvalidPathChars()));
}
2019-05-28 22:11:40 +02:00
}
}