mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-23 00:18:47 +00:00
Introduces type: - Endianness Introduces Read methods: - ReadInt16 - ReadInt32 - ReadInt64 - ReadUInt16 - ReadUInt32 - ReadUInt64 Introduces Write methods: - Write(short) - Write(int) - Write(long) - Write(ushort) - Write(uint) - Write(ulong) Introduces internal "Util" class to provide internal-only helper methods - SwapIfNeeded (reverse a buffer on Endianness mismatch)
This commit is contained in:
parent
ef9dc29e42
commit
99fd511714
16
X10D/src/Endianness.cs
Normal file
16
X10D/src/Endianness.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace X10D
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an enumeration of endianness values.
|
||||
/// </summary>
|
||||
public enum Endianness
|
||||
{
|
||||
[Description("The value should be read as though it uses little endian encoding.")]
|
||||
LittleEndian,
|
||||
|
||||
[Description("The value should be read as though it uses big endian encoding.")]
|
||||
BigEndian
|
||||
}
|
||||
}
|
@ -9,6 +9,9 @@ namespace X10D.StreamExtensions
|
||||
/// </summary>
|
||||
public static class StreamExtensions
|
||||
{
|
||||
private static readonly Endianness DefaultEndianness =
|
||||
BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash of a stream using the specified hash algorithm.
|
||||
/// </summary>
|
||||
@ -49,5 +52,359 @@ namespace X10D.StreamExtensions
|
||||
|
||||
return crypt.ComputeHash(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte signed integer from the current stream and advances the current position of the stream by two
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>A 2-byte signed integer read from the current stream.</returns>
|
||||
public static short ReadInt16(this Stream stream)
|
||||
{
|
||||
return stream.ReadInt16(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte signed integer from the current stream and advances the current position of the stream by two
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>A 2-byte signed integer read from the current stream.</returns>
|
||||
public static short ReadInt16(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<short>(stream, endianness);
|
||||
return BitConverter.ToInt16(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte signed integer from the current stream and advances the current position of the stream by four
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>A 4-byte signed integer read from the current stream.</returns>
|
||||
public static int ReadInt32(this Stream stream)
|
||||
{
|
||||
return stream.ReadInt32(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte signed integer from the current stream and advances the current position of the stream by four
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>A 4-byte signed integer read from the current stream.</returns>
|
||||
public static int ReadInt32(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<int>(stream, endianness);
|
||||
return BitConverter.ToInt32(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte signed integer from the current stream and advances the current position of the stream by eight
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>An 8-byte signed integer read from the current stream.</returns>
|
||||
public static long ReadInt64(this Stream stream)
|
||||
{
|
||||
return stream.ReadInt64(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte signed integer from the current stream and advances the current position of the stream by eight
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>An 8-byte signed integer read from the current stream.</returns>
|
||||
public static long ReadInt64(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<long>(stream, endianness);
|
||||
return BitConverter.ToInt64(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte unsigned integer from the current stream and advances the current position of the stream by two
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>A 2-byte unsigned integer read from the current stream.</returns>
|
||||
public static ushort ReadUInt16(this Stream stream)
|
||||
{
|
||||
return stream.ReadUInt16(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte unsigned integer from the current stream and advances the current position of the stream by two
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>A 2-byte unsigned integer read from the current stream.</returns>
|
||||
public static ushort ReadUInt16(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<ushort>(stream, endianness);
|
||||
return BitConverter.ToUInt16(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte unsigned integer from the current stream and advances the current position of the stream by four
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>A 4-byte unsigned integer read from the current stream.</returns>
|
||||
public static uint ReadUInt32(this Stream stream)
|
||||
{
|
||||
return stream.ReadUInt32(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte unsigned integer from the current stream and advances the current position of the stream by four
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>A 4-byte unsigned integer read from the current stream.</returns>
|
||||
public static uint ReadUInt32(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<uint>(stream, endianness);
|
||||
return BitConverter.ToUInt32(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte unsigned integer from the current stream and advances the current position of the stream by eight
|
||||
/// bytes using the default endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <returns>An 8-byte unsigned integer read from the current stream.</returns>
|
||||
public static ulong ReadUInt64(this Stream stream)
|
||||
{
|
||||
return stream.ReadUInt64(DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte unsigned integer from the current stream and advances the current position of the stream by eight
|
||||
/// bytes using a specified endian encoding.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>An 8-byte unsigned integer read from the current stream.</returns>
|
||||
public static ulong ReadUInt64(this Stream stream, Endianness endianness)
|
||||
{
|
||||
var value = ReadInternal<ulong>(stream, endianness);
|
||||
return BitConverter.ToUInt64(value, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a two-byte signed integer to the current stream using the system's default endian encoding, and advances
|
||||
/// the stream position by two bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The two-byte signed integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, short value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a two-byte signed integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by two bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The two-byte signed integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, short value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a four-byte signed integer to the current stream using the system's default endian encoding, and advances
|
||||
/// the stream position by four bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The four-byte signed integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, int value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a four-byte signed integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by four bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The four-byte signed integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, int value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an eight-byte signed integer to the current stream using the system's default endian encoding, and advances
|
||||
/// the stream position by eight bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The eight-byte signed integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, long value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an eight-byte signed integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by eight bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The eight-byte signed integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
public static int Write(this Stream stream, long value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a two-byte unsigned integer to the current stream using the system's default endian encoding, and advances
|
||||
/// the stream position by two bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The two-byte unsigned integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, ushort value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a two-byte unsigned integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by two bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The two-byte unsigned integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, ushort value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a four-byte unsigned integer to the current stream using the system's default endian encoding, and advances
|
||||
/// the stream position by four bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The four-byte unsigned integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, uint value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a four-byte unsigned integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by four bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The four-byte unsigned integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, uint value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an eight-byte unsigned integer to the current stream using the system's default endian encoding, and
|
||||
/// advances the stream position by eight bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The eight-byte unsigned integer to write.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, ulong value)
|
||||
{
|
||||
return stream.Write(value, DefaultEndianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an eight-byte signed integer to the current stream using the specified endian encoding, and advances the
|
||||
/// stream position by eight bytes.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to which the value should be written.</param>
|
||||
/// <param name="value">The eight-byte signed integer to write.</param>
|
||||
/// <param name="endianness">The endian encoding to use.</param>
|
||||
/// <returns>The number of bytes written to the stream.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static int Write(this Stream stream, ulong value, Endianness endianness)
|
||||
{
|
||||
var buffer = BitConverter.GetBytes(value);
|
||||
return stream.WriteInternal(buffer, endianness);
|
||||
}
|
||||
|
||||
private static unsafe byte[] ReadInternal<T>(this Stream stream, Endianness endianness)
|
||||
where T : unmanaged
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (!stream.CanRead)
|
||||
{
|
||||
throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading, nameof(stream));
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(typeof(Endianness), endianness))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(endianness));
|
||||
}
|
||||
|
||||
var buffer = new byte[sizeof(T)];
|
||||
stream.Read(buffer, 0, buffer.Length);
|
||||
Util.SwapIfNeeded(ref buffer, endianness);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static int WriteInternal(this Stream stream, byte[] value, Endianness endianness)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (!stream.CanWrite)
|
||||
{
|
||||
throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting, nameof(stream));
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(typeof(Endianness), endianness))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(endianness));
|
||||
}
|
||||
|
||||
byte[] clone = (byte[])value.Clone();
|
||||
Util.SwapIfNeeded(ref clone, endianness);
|
||||
var preWritePosition = stream.Position;
|
||||
stream.Write(clone, 0, clone.Length);
|
||||
return (int)(stream.Position - preWritePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
X10D/src/Util.cs
Normal file
21
X10D/src/Util.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace X10D
|
||||
{
|
||||
internal static class Util
|
||||
{
|
||||
public static void SwapIfNeeded(ref byte[] buffer, Endianness endianness)
|
||||
{
|
||||
if (buffer is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
var swapNeeded = BitConverter.IsLittleEndian == (endianness == Endianness.BigEndian);
|
||||
if (swapNeeded)
|
||||
{
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user