mirror of
https://github.com/SabreTools/SabreTools.IO.git
synced 2026-02-13 05:35:34 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
886bc208dc | ||
|
|
5dc6290a87 | ||
|
|
c8eb7d4d80 | ||
|
|
6035e2acaa | ||
|
|
f51b19998f |
363
ByteArrayExtensions.cs
Normal file
363
ByteArrayExtensions.cs
Normal file
@@ -0,0 +1,363 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for byte arrays
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Add U/Int24 and U/Int48 methods</remarks>
|
||||
public static class ByteArrayExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Read a UInt8 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static byte ReadByte(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 1);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 1);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt8[] and increment the pointer to an array
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static byte[] ReadBytes(this byte[] content, ref int offset, int count)
|
||||
#else
|
||||
public static byte[]? ReadBytes(this byte[]? content, ref int offset, int count)
|
||||
#endif
|
||||
{
|
||||
// If the byte array is invalid, don't do anything
|
||||
if (content == null)
|
||||
return null;
|
||||
|
||||
// If there's an invalid byte count, don't do anything
|
||||
if (count <= 0 || offset >= content.Length)
|
||||
return null;
|
||||
|
||||
// Allocate enough space for the data requested
|
||||
byte[] buffer = new byte[count];
|
||||
|
||||
// If we have less data left than requested, only read until the end
|
||||
if (offset + count >= content.Length)
|
||||
count = content.Length - offset;
|
||||
|
||||
// If we have a non-zero count, copy the data into the array
|
||||
if (count > 0)
|
||||
Array.Copy(content, offset, buffer, 0, Math.Min(count, content.Length - offset));
|
||||
|
||||
// Increment the offset and return
|
||||
offset += count;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int8 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static sbyte ReadSByte(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 1);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 1);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return (sbyte)buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Char and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static char ReadChar(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 1);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 1);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return (char)buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int16 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static short ReadInt16(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 2);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 2);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int16 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static short ReadInt16BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 2);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 2);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt16 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static ushort ReadUInt16(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 2);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 2);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt16 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static ushort ReadUInt16BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 2);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 2);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int32 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static int ReadInt32(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 4);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 4);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int32 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static int ReadInt32BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 4);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 4);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt32 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static uint ReadUInt32(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 4);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 4);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt32 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static uint ReadUInt32BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 4);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 4);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int64 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static long ReadInt64(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 8);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 8);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int64 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static long ReadInt64BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 8);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 8);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt64 and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static ulong ReadUInt64(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 8);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 8);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt64 in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static ulong ReadUInt64BigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 8);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 8);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Guid and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static Guid ReadGuid(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 16);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 16);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
return new Guid(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Guid in big-endian format and increment the pointer to an array
|
||||
/// </summary>
|
||||
public static Guid ReadGuidBigEndian(this byte[] content, ref int offset)
|
||||
{
|
||||
#if NET48
|
||||
byte[] buffer = content.ReadBytes(ref offset, 16);
|
||||
#else
|
||||
byte[]? buffer = content.ReadBytes(ref offset, 16);
|
||||
#endif
|
||||
if (buffer == null)
|
||||
return default;
|
||||
|
||||
Array.Reverse(buffer);
|
||||
return new Guid(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string ReadString(this byte[] content, ref int offset) => content.ReadString(ref offset, Encoding.Default);
|
||||
#else
|
||||
public static string? ReadString(this byte[] content, ref int offset) => content.ReadString(ref offset, Encoding.Default);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string ReadString(this byte[] content, ref int offset, Encoding encoding)
|
||||
#else
|
||||
public static string? ReadString(this byte[] content, ref int offset, Encoding encoding)
|
||||
#endif
|
||||
{
|
||||
if (offset >= content.Length)
|
||||
return null;
|
||||
|
||||
byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' });
|
||||
int charWidth = nullTerminator.Length;
|
||||
|
||||
List<char> keyChars = new List<char>();
|
||||
while (offset < content.Length)
|
||||
{
|
||||
char c = encoding.GetChars(content, offset, charWidth)[0];
|
||||
keyChars.Add(c);
|
||||
offset += charWidth;
|
||||
|
||||
if (c == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
return new string(keyChars.ToArray()).TrimEnd('\0');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,5 @@ This library comprises I/O functionality for the following file types:
|
||||
- Separated-Value files (e.g. CSV, SSV, TSV)
|
||||
|
||||
There are also some extensions that are useful for wrapping common functionality required by SabreTools.
|
||||
|
||||
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.IO).
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Version>1.1.0</Version>
|
||||
<Version>1.1.1</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
|
||||
@@ -1,12 +1,247 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions to Stream functionality
|
||||
/// Extensions for Streams
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Add U/Int24 and U/Int48 methods</remarks>
|
||||
public static class StreamExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Read a UInt8 from the stream
|
||||
/// </summary>
|
||||
public static byte ReadByteValue(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt8[] from the stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static byte[] ReadBytes(this Stream stream, int count)
|
||||
#else
|
||||
public static byte[]? ReadBytes(this Stream stream, int count)
|
||||
#endif
|
||||
{
|
||||
// If there's an invalid byte count, don't do anything
|
||||
if (count <= 0)
|
||||
return null;
|
||||
|
||||
byte[] buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int8 from the stream
|
||||
/// </summary>
|
||||
public static sbyte ReadSByte(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return (sbyte)buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Char from the stream
|
||||
/// </summary>
|
||||
public static char ReadChar(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return (char)buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int16 from the stream
|
||||
/// </summary>
|
||||
public static short ReadInt16(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int16 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static short ReadInt16BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt16 from the stream
|
||||
/// </summary>
|
||||
public static ushort ReadUInt16(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt16 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static ushort ReadUInt16BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an Int32 from the stream
|
||||
/// </summary>
|
||||
public static int ReadInt32(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an Int32 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static int ReadInt32BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt32 from the stream
|
||||
/// </summary>
|
||||
public static uint ReadUInt32(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
return BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt32 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static uint ReadUInt32BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int64 from the stream
|
||||
/// </summary>
|
||||
public static long ReadInt64(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
return BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Int64 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static long ReadInt64BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt64 from the stream
|
||||
/// </summary>
|
||||
public static ulong ReadUInt64(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a UInt64 from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static ulong ReadUInt64BigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Guid from the stream
|
||||
/// </summary>
|
||||
public static Guid ReadGuid(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[16];
|
||||
stream.Read(buffer, 0, 16);
|
||||
return new Guid(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Guid from the stream in big-endian format
|
||||
/// </summary>
|
||||
public static Guid ReadGuidBigEndian(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[16];
|
||||
stream.Read(buffer, 0, 16);
|
||||
Array.Reverse(buffer);
|
||||
return new Guid(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string ReadString(this Stream stream) => stream.ReadString(Encoding.Default);
|
||||
#else
|
||||
public static string? ReadString(this Stream stream) => stream.ReadString(Encoding.Default);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string ReadString(this Stream stream, Encoding encoding)
|
||||
#else
|
||||
public static string? ReadString(this Stream stream, Encoding encoding)
|
||||
#endif
|
||||
{
|
||||
if (stream.Position >= stream.Length)
|
||||
return null;
|
||||
|
||||
byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' });
|
||||
int charWidth = nullTerminator.Length;
|
||||
|
||||
List<byte> tempBuffer = new List<byte>();
|
||||
|
||||
byte[] buffer = new byte[charWidth];
|
||||
while (stream.Position < stream.Length && stream.Read(buffer, 0, charWidth) != 0 && !buffer.SequenceEqual(nullTerminator))
|
||||
{
|
||||
tempBuffer.AddRange(buffer);
|
||||
}
|
||||
|
||||
return encoding.GetString(tempBuffer.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seek to a specific point in the stream, if possible
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user