mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-10 03:05:42 +00:00
- Delegate argument validation to Validate class - Fix ReadDecimal - Add Write(decimal)
This commit is contained in:
parent
88244def34
commit
4d31eee600
44
X10D/src/StreamExtensions/StreamExtensions.Internal.cs
Normal file
44
X10D/src/StreamExtensions/StreamExtensions.Internal.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace X10D.StreamExtensions
|
||||||
|
{
|
||||||
|
public static partial class StreamExtensions
|
||||||
|
{
|
||||||
|
private static unsafe byte[] ReadInternal<T>(this Stream stream, Endianness endianness)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
var buffer = new byte[sizeof(T)];
|
||||||
|
stream.Read(buffer, 0, buffer.Length);
|
||||||
|
SwapIfNeeded(ref buffer, endianness);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SwapIfNeeded(ref byte[] buffer, Endianness endianness)
|
||||||
|
{
|
||||||
|
var swapNeeded = BitConverter.IsLittleEndian == (endianness == Endianness.BigEndian);
|
||||||
|
if (swapNeeded)
|
||||||
|
{
|
||||||
|
Array.Reverse(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int WriteInternal(this Stream stream, byte[] value, Endianness endianness)
|
||||||
|
{
|
||||||
|
var clone = (byte[])value.Clone();
|
||||||
|
SwapIfNeeded(ref clone, endianness);
|
||||||
|
var preWritePosition = stream.Position;
|
||||||
|
stream.Write(clone, 0, clone.Length);
|
||||||
|
return (int)(stream.Position - preWritePosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
private static int WriteInternal(this Stream stream, Span<byte> value)
|
||||||
|
{
|
||||||
|
var preWritePosition = stream.Position;
|
||||||
|
stream.Write(value);
|
||||||
|
return (int)(stream.Position - preWritePosition);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
#if NET5_0
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
#endif
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
@ -7,7 +10,7 @@ namespace X10D.StreamExtensions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extension methods for <see cref="Stream" />.
|
/// Extension methods for <see cref="Stream" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StreamExtensions
|
public static partial class StreamExtensions
|
||||||
{
|
{
|
||||||
private static readonly Endianness DefaultEndianness =
|
private static readonly Endianness DefaultEndianness =
|
||||||
BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian;
|
BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian;
|
||||||
@ -73,22 +76,17 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>A decimal value read from the stream.</returns>
|
/// <returns>A decimal value read from the stream.</returns>
|
||||||
public static decimal ReadDecimal(this Stream stream, Endianness endianness)
|
public static decimal ReadDecimal(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
const int decimalSize = sizeof(decimal);
|
const int decimalSize = sizeof(decimal);
|
||||||
const int int32Size = sizeof(int);
|
const int int32Size = sizeof(int);
|
||||||
const int partitionSize = decimalSize / int32Size;
|
const int partitionSize = decimalSize / int32Size;
|
||||||
|
|
||||||
var buffer = new byte[decimalSize];
|
|
||||||
stream.Read(buffer, 0, decimalSize);
|
|
||||||
|
|
||||||
Util.SwapIfNeeded(ref buffer, endianness);
|
|
||||||
|
|
||||||
var bits = new int[partitionSize];
|
var bits = new int[partitionSize];
|
||||||
for (var index = 0; index < partitionSize; index += int32Size)
|
for (var index = 0; index < partitionSize; index++)
|
||||||
{
|
{
|
||||||
bits[index] = (buffer[index + 0] << 24) // +0 because aligned code is best code
|
bits[index] = stream.ReadInt32(endianness);
|
||||||
| (buffer[index + 1] << 16)
|
|
||||||
| (buffer[index + 2] << 8)
|
|
||||||
| (buffer[index + 3] << 0); // don't @ me
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new decimal(bits);
|
return new decimal(bits);
|
||||||
@ -114,8 +112,20 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>A double-precision floating point value read from the stream.</returns>
|
/// <returns>A double-precision floating point value read from the stream.</returns>
|
||||||
public static double ReadDouble(this Stream stream, Endianness endianness)
|
public static double ReadDouble(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadDoubleLittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadDoubleBigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<double>(stream, endianness);
|
var value = ReadInternal<double>(stream, endianness);
|
||||||
return BitConverter.ToDouble(value, 0);
|
return BitConverter.ToDouble(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -138,8 +148,20 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>An two-byte unsigned integer read from the stream.</returns>
|
/// <returns>An two-byte unsigned integer read from the stream.</returns>
|
||||||
public static short ReadInt16(this Stream stream, Endianness endianness)
|
public static short ReadInt16(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadInt16LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadInt16BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<short>(stream, endianness);
|
var value = ReadInternal<short>(stream, endianness);
|
||||||
return BitConverter.ToInt16(value, 0);
|
return BitConverter.ToInt16(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -162,8 +184,20 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>An four-byte unsigned integer read from the stream.</returns>
|
/// <returns>An four-byte unsigned integer read from the stream.</returns>
|
||||||
public static int ReadInt32(this Stream stream, Endianness endianness)
|
public static int ReadInt32(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadInt32LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadInt32BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<int>(stream, endianness);
|
var value = ReadInternal<int>(stream, endianness);
|
||||||
return BitConverter.ToInt32(value, 0);
|
return BitConverter.ToInt32(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -186,8 +220,20 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>An eight-byte unsigned integer read from the stream.</returns>
|
/// <returns>An eight-byte unsigned integer read from the stream.</returns>
|
||||||
public static long ReadInt64(this Stream stream, Endianness endianness)
|
public static long ReadInt64(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadInt64LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadInt64BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<long>(stream, endianness);
|
var value = ReadInternal<long>(stream, endianness);
|
||||||
return BitConverter.ToInt64(value, 0);
|
return BitConverter.ToInt64(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -210,8 +256,20 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>A single-precision floating point value read from the stream.</returns>
|
/// <returns>A single-precision floating point value read from the stream.</returns>
|
||||||
public static double ReadSingle(this Stream stream, Endianness endianness)
|
public static double ReadSingle(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
var value = ReadInternal<double>(stream, endianness);
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadSingleLittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadSingleBigEndian(buffer);
|
||||||
|
#else
|
||||||
|
var value = ReadInternal<float>(stream, endianness);
|
||||||
return BitConverter.ToSingle(value, 0);
|
return BitConverter.ToSingle(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -236,8 +294,20 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static ushort ReadUInt16(this Stream stream, Endianness endianness)
|
public static ushort ReadUInt16(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadUInt16LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadUInt16BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<ushort>(stream, endianness);
|
var value = ReadInternal<ushort>(stream, endianness);
|
||||||
return BitConverter.ToUInt16(value, 0);
|
return BitConverter.ToUInt16(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -262,8 +332,20 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static uint ReadUInt32(this Stream stream, Endianness endianness)
|
public static uint ReadUInt32(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadUInt32LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadUInt32BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<uint>(stream, endianness);
|
var value = ReadInternal<uint>(stream, endianness);
|
||||||
return BitConverter.ToUInt32(value, 0);
|
return BitConverter.ToUInt32(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -288,8 +370,20 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static ulong ReadUInt64(this Stream stream, Endianness endianness)
|
public static ulong ReadUInt64(this Stream stream, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
stream.Read(buffer);
|
||||||
|
|
||||||
|
return endianness == Endianness.LittleEndian
|
||||||
|
? BinaryPrimitives.ReadUInt64LittleEndian(buffer)
|
||||||
|
: BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||||
|
#else
|
||||||
var value = ReadInternal<ulong>(stream, endianness);
|
var value = ReadInternal<ulong>(stream, endianness);
|
||||||
return BitConverter.ToUInt64(value, 0);
|
return BitConverter.ToUInt64(value, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -314,8 +408,26 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>The number of bytes written to the stream.</returns>
|
/// <returns>The number of bytes written to the stream.</returns>
|
||||||
public static int Write(this Stream stream, short value, Endianness endianness)
|
public static int Write(this Stream stream, short value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(short)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt16LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt16BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -340,8 +452,26 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>The number of bytes written to the stream.</returns>
|
/// <returns>The number of bytes written to the stream.</returns>
|
||||||
public static int Write(this Stream stream, int value, Endianness endianness)
|
public static int Write(this Stream stream, int value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt32LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt32BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -366,8 +496,26 @@ namespace X10D.StreamExtensions
|
|||||||
/// <returns>The number of bytes written to the stream.</returns>
|
/// <returns>The number of bytes written to the stream.</returns>
|
||||||
public static int Write(this Stream stream, long value, Endianness endianness)
|
public static int Write(this Stream stream, long value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(long)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt64LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt64BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -394,8 +542,26 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static int Write(this Stream stream, ushort value, Endianness endianness)
|
public static int Write(this Stream stream, ushort value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(ushort)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt16LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt16BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -422,8 +588,26 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static int Write(this Stream stream, uint value, Endianness endianness)
|
public static int Write(this Stream stream, uint value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(uint)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt32BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -450,55 +634,113 @@ namespace X10D.StreamExtensions
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static int Write(this Stream stream, ulong value, Endianness endianness)
|
public static int Write(this Stream stream, ulong value, Endianness endianness)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(ulong)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt64LittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteUInt64BigEndian(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.WriteInternal(buffer);
|
||||||
|
#else
|
||||||
var buffer = BitConverter.GetBytes(value);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return stream.WriteInternal(buffer, endianness);
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe byte[] ReadInternal<T>(this Stream stream, Endianness endianness)
|
/// <summary>
|
||||||
where T : unmanaged
|
/// Writes a single-precision floating point value 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 single-precision floating point value 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, float value, Endianness endianness)
|
||||||
{
|
{
|
||||||
if (stream is null)
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(float)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(stream));
|
BinaryPrimitives.WriteSingleLittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteSingleBigEndian(buffer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stream.CanRead)
|
return stream.WriteInternal(buffer);
|
||||||
{
|
#else
|
||||||
throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading, nameof(stream));
|
var buffer = BitConverter.GetBytes(value);
|
||||||
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(Endianness), endianness))
|
/// <summary>
|
||||||
|
/// Writes a double-precision floating point value 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 double-precision floating point value 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, double value, Endianness endianness)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(endianness));
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
|
|
||||||
|
#if NET5_0
|
||||||
|
Span<byte> buffer = stackalloc byte[sizeof(double)];
|
||||||
|
|
||||||
|
if (endianness == Endianness.LittleEndian)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteDoubleLittleEndian(buffer, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteDoubleBigEndian(buffer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = new byte[sizeof(T)];
|
return stream.WriteInternal(buffer);
|
||||||
stream.Read(buffer, 0, buffer.Length);
|
#else
|
||||||
Util.SwapIfNeeded(ref buffer, endianness);
|
var buffer = BitConverter.GetBytes(value);
|
||||||
return buffer;
|
return stream.WriteInternal(buffer, endianness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int WriteInternal(this Stream stream, byte[] value, Endianness endianness)
|
/// <summary>
|
||||||
|
/// Writes a decimal value to the current stream using the specified endian encoding, and advances the stream position
|
||||||
|
/// by sixteen bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream to which the value should be written.</param>
|
||||||
|
/// <param name="value">The decimal value 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, decimal value, Endianness endianness)
|
||||||
{
|
{
|
||||||
if (stream is null)
|
Validate.IsNotNull(stream, nameof(stream));
|
||||||
{
|
Validate.IsDefined(endianness, nameof(endianness));
|
||||||
throw new ArgumentNullException(nameof(stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stream.CanWrite)
|
var bits = decimal.GetBits(value);
|
||||||
{
|
|
||||||
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;
|
var preWritePosition = stream.Position;
|
||||||
stream.Write(clone, 0, clone.Length);
|
|
||||||
|
foreach (var section in bits)
|
||||||
|
{
|
||||||
|
stream.Write(section, endianness);
|
||||||
|
}
|
||||||
|
|
||||||
return (int)(stream.Position - preWritePosition);
|
return (int)(stream.Position - preWritePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
X10D/src/Validate.cs
Normal file
24
X10D/src/Validate.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace X10D
|
||||||
|
{
|
||||||
|
internal static class Validate
|
||||||
|
{
|
||||||
|
public static void IsDefined<T>(T value, string argumentName)
|
||||||
|
where T : Enum
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(T), value))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(argumentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void IsNotNull<T>(T argument, string argumentName)
|
||||||
|
{
|
||||||
|
if (argument is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(argumentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user