25 Commits
1.7.6 ... 1.8.0

Author SHA1 Message Date
Matt Nadareski
16b238539b Bump version 2025-10-27 22:09:15 -04:00
Matt Nadareski
68f49eeb48 Add Bitwise Binary Operators tests 2025-10-27 16:47:36 -04:00
Matt Nadareski
c5ecd41a8f Add Shift Binary Operators tests 2025-10-27 16:43:05 -04:00
Matt Nadareski
9ab9dd4ff8 Add Bitwise Unary Operators tests 2025-10-27 16:38:45 -04:00
Matt Nadareski
867c8d11da Fix unary operator tests 2025-10-27 16:28:14 -04:00
Matt Nadareski
65dbb7a31a Add Arithmetic Binary Operators tests 2025-10-27 16:18:45 -04:00
Matt Nadareski
1eaf7954fe Add Arithmetic Unary Operators tests 2025-10-27 16:12:12 -04:00
Matt Nadareski
a602a07514 Fill out bitwise operators for both-endian 2025-10-27 16:06:01 -04:00
Matt Nadareski
466b0e90e7 Fill out arithmetic operators for both-endian 2025-10-27 15:52:48 -04:00
Matt Nadareski
abdf50c9e0 Add bitwise AND and OR operations to both-endian 2025-10-27 15:34:32 -04:00
Matt Nadareski
12341ba6aa Simplify Numerics namespace 2025-10-27 14:12:52 -04:00
Matt Nadareski
70b78f861c Revert "Add base type operator support to both-endian"
This reverts commit 5b306ce9e8.
2025-10-27 14:07:01 -04:00
Matt Nadareski
5b306ce9e8 Add base type operator support to both-endian 2025-10-27 14:02:52 -04:00
Matt Nadareski
2b6fc200e2 Add Latin1 and BigEndianUnicode extensions 2025-10-27 12:22:02 -04:00
Matt Nadareski
7c63f44c75 Add both-endian write extensions 2025-10-27 12:01:52 -04:00
Matt Nadareski
edd3e6eef2 Add both-endian try read extensions 2025-10-27 11:21:29 -04:00
Matt Nadareski
244b7411d4 Add both-endian peek read extensions 2025-10-27 10:43:54 -04:00
Matt Nadareski
fb60f1fed5 Add both-endian exact read extensions 2025-10-27 10:03:17 -04:00
Matt Nadareski
8f06bf5859 Add both-endian numeric types 2025-10-27 09:09:00 -04:00
Matt Nadareski
2c5d7ad56b Update rolling tag 2025-10-26 20:31:52 -04:00
Matt Nadareski
46996c10e5 Add Peek implementations for reading 2025-10-15 09:59:07 -04:00
Matt Nadareski
7491821679 Add origin-based SeekIfPossible 2025-10-15 09:37:41 -04:00
Matt Nadareski
8fe404e732 Remove some nonsensical endian methods 2025-10-14 20:45:02 -04:00
Matt Nadareski
793168fbe5 Add TryGet implementations for reading 2025-10-14 20:42:32 -04:00
Matt Nadareski
67b6118cc1 Add functionality from Transform tool 2025-10-14 13:58:40 -04:00
41 changed files with 14967 additions and 111 deletions

View File

@@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
@@ -27,6 +27,14 @@ jobs:
- name: Run publish script
run: ./publish-nix.sh
- name: Update rolling tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f rolling
git push origin :refs/tags/rolling || true
git push origin rolling --force
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:

View File

@@ -92,6 +92,33 @@ Custom `Stream` implementations that are required for specialized use:
- `ReadOnlyCompositeStream`: A readonly stream implementation that wraps multiple source streams in a set order
- `ViewStream`: A readonly stream implementation representing a view into source data
### `SabreTools.IO.Transform`
File and stream implementations of common data transformations:
- Combine using either ordered concatenation or interleaving
- Split by even/odd chunks or based on block size
- Convert data either by bit-swapping, byte-swapping, word-swapping, or word/byte-swapping
### `SabreTools.Numerics`
Custom numeric types and related functionality.
#### Supported Numeric Types
| Type Name | Description |
| --- | --- |
| `BothInt8` | Both-endian `Int8` value |
| `BothUInt8` | Both-endian `UInt8` value |
| `BothInt16` | Both-endian `Int16` value |
| `BothUInt16` | Both-endian `UInt16` value |
| `BothInt32` | Both-endian `Int32` value |
| `BothUInt32` | Both-endian `UInt32` value |
| `BothInt64` | Both-endian `Int64` value |
| `BothUInt64` | Both-endian `UInt64` value |
**Both-endian** or **bi-endian** numbers are represented by a little-endian value followed by a big-endian value, where both values are the same number.
### `SabreTools.Text.Compare`
Classes focused on string comparison by natural sorting. For example, "5" would be sorted before "100".

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteByteBothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(2).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadByteBothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteBytesTest()
{
@@ -68,6 +80,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteSByteBothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(2).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadSByteBothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteCharTest()
{
@@ -109,6 +133,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt16BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(4).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadInt16BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt16Test()
{
@@ -130,6 +166,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt16BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(4).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadUInt16BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteHalfTest()
{
@@ -214,6 +262,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt32BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(8).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadInt32BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt32Test()
{
@@ -235,6 +295,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt32BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(8).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadUInt32BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteSingleTest()
{
@@ -319,6 +391,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt64BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(16).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadInt64BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt64Test()
{
@@ -340,6 +424,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt64BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
var bw = new BinaryWriter(stream);
byte[] expected = _bytes.Take(16).ToArray();
int offset = 0;
bw.WriteBothEndian(_bytes.ReadUInt64BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteDoubleTest()
{

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteByteBothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(2).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadByteBothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteBytesTest()
{
@@ -71,6 +83,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteSByteBothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(2).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadSByteBothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteCharTest()
{
@@ -115,6 +139,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteInt16BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(4).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadInt16BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt16Test()
{
@@ -137,6 +173,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt16BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(4).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadUInt16BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteHalfTest()
{
@@ -225,6 +273,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteInt32BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(8).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadInt32BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt32Test()
{
@@ -247,6 +307,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt32BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(8).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadUInt32BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteSingleTest()
{
@@ -335,6 +407,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteInt64BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(16).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadInt64BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt64Test()
{
@@ -357,6 +441,18 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteUInt64BothEndianTest()
{
byte[] buffer = new byte[16];
int offset = 0;
byte[] expected = _bytes.Take(16).ToArray();
int readOffset = 0;
buffer.WriteBothEndian(ref offset, _bytes.ReadUInt64BothEndian(ref readOffset));
ValidateBytes(expected, buffer);
}
[Fact]
public void WriteDoubleTest()
{

View File

@@ -313,6 +313,52 @@ namespace SabreTools.IO.Test.Extensions
Assert.Equal(13, actual);
}
[Theory]
[InlineData(SeekOrigin.Begin)]
[InlineData(SeekOrigin.Current)]
[InlineData(SeekOrigin.End)]
public void SeekIfPossible_NonSeekable_OriginTest(SeekOrigin origin)
{
var stream = new NonSeekableStream();
long actual = stream.SeekIfPossible(0, origin);
Assert.Equal(8, actual);
}
[Theory]
[InlineData(SeekOrigin.Begin)]
[InlineData(SeekOrigin.Current)]
[InlineData(SeekOrigin.End)]
public void SeekIfPossible_NonPositionable_OriginTest(SeekOrigin origin)
{
var stream = new NonPositionableStream();
long actual = stream.SeekIfPossible(0, origin);
Assert.Equal(-1, actual);
}
[Theory]
[InlineData(SeekOrigin.Begin)]
[InlineData(SeekOrigin.Current)]
[InlineData(SeekOrigin.End)]
public void SeekIfPossible_HiddenNonSeekable_OriginTest(SeekOrigin origin)
{
var stream = new HiddenNonSeekableStream();
long actual = stream.SeekIfPossible(0, origin);
Assert.Equal(-1, actual);
}
[Theory]
[InlineData(SeekOrigin.Begin, 5, 5)]
[InlineData(SeekOrigin.Current, 5, 7)]
[InlineData(SeekOrigin.End, -5, 11)]
public void SeekIfPossible_Seekable_OriginTest(SeekOrigin origin, long offset, long expected)
{
var stream = new MemoryStream(new byte[16], 0, 16, false, true);
stream.Position = 2;
long actual = stream.SeekIfPossible(offset, origin);
Assert.Equal(expected, actual);
}
#endregion
#region SegmentValid

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteByteBothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(2).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadByteBothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteBytesTest()
{
@@ -67,6 +78,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteSByteBothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(2).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadSByteBothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteCharTest()
{
@@ -106,6 +128,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt16BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(4).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadInt16BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt16Test()
{
@@ -126,6 +159,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt16BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(4).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadUInt16BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteHalfTest()
{
@@ -206,6 +250,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt32BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(8).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadInt32BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt32Test()
{
@@ -226,6 +281,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt32BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(8).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadUInt32BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteSingleTest()
{
@@ -306,6 +372,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteInt64BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(16).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadInt64BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt64Test()
{
@@ -326,6 +403,17 @@ namespace SabreTools.IO.Test.Extensions
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteUInt64BothEndianTest()
{
var stream = new MemoryStream(new byte[16], 0, 16, true, true);
byte[] expected = _bytes.Take(16).ToArray();
int offset = 0;
stream.WriteBothEndian(_bytes.ReadUInt64BothEndian(ref offset));
ValidateBytes(expected, stream.GetBuffer());
}
[Fact]
public void WriteDoubleTest()
{

View File

@@ -0,0 +1,249 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothInt16Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(short le, short be, bool expected)
{
var val = new BothInt16(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
short expected = 1;
var val = new BothInt16(expected, expected);
short to = (short)val;
Assert.Equal(expected, to);
BothInt16 back = (BothInt16)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(short le, int expected)
{
short compare = 1;
var val = new BothInt16(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((short)1).GetTypeCode();
var val = new BothInt16(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothInt16(1, 1);
bool expectedBool = Convert.ToBoolean((short)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((short)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((short)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((short)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((short)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((short)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((short)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((short)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((short)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((short)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((short)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((short)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((short)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((short)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((short)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(short le, short be, bool expected)
{
var val = new BothInt16(le, be);
var equalTo = new BothInt16(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(short le, short be, bool expected)
{
var val = new BothInt16(le, be);
short equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothInt16(2, 2);
short expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt16(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt16(2, 2);
expected = 2;
BothInt16 actual = +valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = -2;
actual = -valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothInt16(3, 3);
var valB = new BothInt16(2, 2);
short expected = 6;
BothInt16 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothInt16(2, 2);
short expected = ~2;
BothInt16 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothInt16(2, 2);
var valB = new BothInt16(1, 1);
short expected = 2 << 1;
BothInt16 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothInt16(3, 3);
var valB = new BothInt16(2, 2);
short expected = 3 & 2;
BothInt16 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,249 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothInt32Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(int le, int be, bool expected)
{
var val = new BothInt32(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
int expected = 1;
var val = new BothInt32(expected, expected);
int to = (int)val;
Assert.Equal(expected, to);
BothInt32 back = (BothInt32)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(int le, int expected)
{
int compare = 1;
var val = new BothInt32(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((int)1).GetTypeCode();
var val = new BothInt32(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothInt32(1, 1);
bool expectedBool = Convert.ToBoolean((int)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((int)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((int)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((int)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((int)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((int)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((int)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((int)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((int)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((int)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((int)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((int)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((int)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((int)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((int)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(int le, int be, bool expected)
{
var val = new BothInt32(le, be);
var equalTo = new BothInt32(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(int le, int be, bool expected)
{
var val = new BothInt32(le, be);
int equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothInt32(2, 2);
int expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt32(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt32(2, 2);
expected = 2;
BothInt32 actual = +valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = -2;
actual = -valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothInt32(3, 3);
var valB = new BothInt32(2, 2);
int expected = 6;
BothInt32 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothInt32(2, 2);
int expected = ~2;
BothInt32 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothInt32(2, 2);
var valB = new BothInt32(1, 1);
int expected = 2 << 1;
BothInt32 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothInt32(3, 3);
var valB = new BothInt32(2, 2);
int expected = 3 & 2;
BothInt32 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,249 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothInt64Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(long le, long be, bool expected)
{
var val = new BothInt64(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
long expected = 1;
var val = new BothInt64(expected, expected);
long to = (long)val;
Assert.Equal(expected, to);
BothInt64 back = (BothInt64)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(long le, int expected)
{
long compare = 1;
var val = new BothInt64(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((long)1).GetTypeCode();
var val = new BothInt64(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothInt64(1, 1);
bool expectedBool = Convert.ToBoolean((long)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((long)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((long)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((long)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((long)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((long)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((long)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((long)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((long)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((long)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((long)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((long)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((long)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((long)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((long)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(long le, long be, bool expected)
{
var val = new BothInt64(le, be);
var equalTo = new BothInt64(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(long le, long be, bool expected)
{
var val = new BothInt64(le, be);
long equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothInt64(2, 2);
long expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt64(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt64(2, 2);
expected = 2;
BothInt64 actual = +valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = -2;
actual = -valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothInt64(3, 3);
var valB = new BothInt64(2, 2);
long expected = 6;
BothInt64 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothInt64(2, 2);
long expected = ~2;
BothInt64 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothInt64(2, 2);
var valB = new BothInt32(1, 1);
long expected = 2 << 1;
BothInt64 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothInt64(3, 3);
var valB = new BothInt64(2, 2);
long expected = 3 & 2;
BothInt64 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,249 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothInt8Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(sbyte le, sbyte be, bool expected)
{
var val = new BothInt8(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
sbyte expected = 1;
var val = new BothInt8(expected, expected);
sbyte to = (sbyte)val;
Assert.Equal(expected, to);
BothInt8 back = (BothInt8)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(sbyte le, int expected)
{
sbyte compare = 1;
var val = new BothInt8(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((sbyte)1).GetTypeCode();
var val = new BothInt8(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothInt8(1, 1);
bool expectedBool = Convert.ToBoolean((sbyte)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((sbyte)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((sbyte)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((sbyte)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((sbyte)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((sbyte)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((sbyte)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((sbyte)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((sbyte)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((sbyte)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((sbyte)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((sbyte)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((sbyte)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((sbyte)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((sbyte)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(sbyte le, sbyte be, bool expected)
{
var val = new BothInt8(le, be);
var equalTo = new BothInt8(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(sbyte le, sbyte be, bool expected)
{
var val = new BothInt8(le, be);
sbyte equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothInt8(2, 2);
sbyte expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt8(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothInt8(2, 2);
expected = 2;
BothInt8 actual = +valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = -2;
actual = -valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothInt8(3, 3);
var valB = new BothInt8(2, 2);
sbyte expected = 6;
BothInt8 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothInt8(2, 2);
sbyte expected = ~2;
BothInt8 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothInt8(2, 2);
var valB = new BothInt8(1, 1);
sbyte expected = 2 << 1;
BothInt8 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothInt8(3, 3);
var valB = new BothInt8(2, 2);
sbyte expected = 3 & 2;
BothInt8 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,238 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothUInt16Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(ushort le, ushort be, bool expected)
{
var val = new BothUInt16(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
ushort expected = 1;
var val = new BothUInt16(expected, expected);
ushort to = (ushort)val;
Assert.Equal(expected, to);
BothUInt16 back = (BothUInt16)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(ushort le, int expected)
{
ushort compare = 1;
var val = new BothUInt16(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((ushort)1).GetTypeCode();
var val = new BothUInt16(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothUInt16(1, 1);
bool expectedBool = Convert.ToBoolean((ushort)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((ushort)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((ushort)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((ushort)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((ushort)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((ushort)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((ushort)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((ushort)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((ushort)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((ushort)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((ushort)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((ushort)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((ushort)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((ushort)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((ushort)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(ushort le, ushort be, bool expected)
{
var val = new BothUInt16(le, be);
var equalTo = new BothUInt16(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(ushort le, ushort be, bool expected)
{
var val = new BothUInt16(le, be);
ushort equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothUInt16(2, 2);
ushort expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothUInt16(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothUInt16(3, 3);
var valB = new BothUInt16(2, 2);
ushort expected = 6;
BothUInt16 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothUInt16(2, 2);
ushort expected = 65533;
BothUInt16 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothUInt16(2, 2);
var valB = new BothUInt16(1, 1);
ushort expected = 2 << 1;
BothUInt16 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothUInt16(3, 3);
var valB = new BothUInt16(2, 2);
ushort expected = 3 & 2;
BothUInt16 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,238 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothUInt32Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(uint le, uint be, bool expected)
{
var val = new BothUInt32(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
uint expected = 1;
var val = new BothUInt32(expected, expected);
uint to = (uint)val;
Assert.Equal(expected, to);
BothUInt32 back = (BothUInt32)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(uint le, int expected)
{
uint compare = 1;
var val = new BothUInt32(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((uint)1).GetTypeCode();
var val = new BothUInt32(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothUInt32(1, 1);
bool expectedBool = Convert.ToBoolean((uint)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((uint)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((uint)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((uint)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((uint)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((uint)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((uint)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((uint)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((uint)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((uint)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((uint)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((uint)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((uint)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((uint)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((uint)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(uint le, uint be, bool expected)
{
var val = new BothUInt32(le, be);
var equalTo = new BothUInt32(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(uint le, uint be, bool expected)
{
var val = new BothUInt32(le, be);
uint equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothUInt32(2, 2);
uint expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothUInt32(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothUInt32(3, 3);
var valB = new BothUInt32(2, 2);
uint expected = 6;
BothUInt32 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothUInt32(2, 2);
uint expected = ~((uint)2);
BothUInt32 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothUInt32(2, 2);
var valB = new BothInt32(1, 1);
uint expected = 2 << 1;
BothUInt32 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothUInt32(3, 3);
var valB = new BothUInt32(2, 2);
uint expected = 3 & 2;
BothUInt32 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,238 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothUInt64Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(ulong le, ulong be, bool expected)
{
var val = new BothUInt64(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
ulong expected = 1;
var val = new BothUInt64(expected, expected);
ulong to = (ulong)val;
Assert.Equal(expected, to);
BothUInt64 back = (BothUInt64)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(ulong le, int expected)
{
ulong compare = 1;
var val = new BothUInt64(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((ulong)1).GetTypeCode();
var val = new BothUInt64(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothUInt64(1, 1);
bool expectedBool = Convert.ToBoolean((ulong)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((ulong)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((ulong)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((ulong)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((ulong)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((ulong)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((ulong)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((ulong)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((ulong)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((ulong)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((ulong)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((ulong)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((ulong)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((ulong)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((ulong)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(ulong le, ulong be, bool expected)
{
var val = new BothUInt64(le, be);
var equalTo = new BothUInt64(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(ulong le, ulong be, bool expected)
{
var val = new BothUInt64(le, be);
ulong equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothUInt64(2, 2);
ulong expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothUInt64(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothUInt64(3, 3);
var valB = new BothUInt64(2, 2);
ulong expected = 6;
BothUInt64 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothUInt64(2, 2);
ulong expected = ~((ulong)2);
BothUInt64 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothUInt64(2, 2);
var valB = new BothInt32(1, 1);
ulong expected = 2 << 1;
BothUInt64 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothUInt64(3, 3);
var valB = new BothUInt64(2, 2);
ulong expected = 3 & 2;
BothUInt64 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,238 @@
using System;
using SabreTools.Numerics;
using Xunit;
namespace SabreTools.IO.Test.Numerics
{
public class BothUInt8Tests
{
[Theory]
[InlineData(0, 0, true)]
[InlineData(0, 1, false)]
public void IsValidTest(byte le, byte be, bool expected)
{
var val = new BothUInt8(le, be);
Assert.Equal(le, val.LittleEndian);
Assert.Equal(be, val.BigEndian);
Assert.Equal(expected, val.IsValid);
}
[Fact]
public void ImplicitConversionTest()
{
byte expected = 1;
var val = new BothUInt8(expected, expected);
byte to = (byte)val;
Assert.Equal(expected, to);
BothUInt8 back = (BothUInt8)to;
Assert.Equal(expected, back.LittleEndian);
Assert.Equal(expected, back.BigEndian);
}
[Theory]
[InlineData(0, -1)]
[InlineData(1, 0)]
[InlineData(2, 1)]
public void CompareToTest(byte le, int expected)
{
byte compare = 1;
var val = new BothUInt8(le, le);
int actual = val.CompareTo(compare);
Assert.Equal(expected, actual);
}
[Fact]
public void GetTypeCodeTest()
{
TypeCode expected = ((byte)1).GetTypeCode();
var val = new BothUInt8(1, 1);
Assert.Equal(expected, val.GetTypeCode());
}
[Fact]
public void ToTypesTest()
{
var val = new BothUInt8(1, 1);
bool expectedBool = Convert.ToBoolean((byte)1);
Assert.Equal(expectedBool, val.ToBoolean(null));
char expectedChar = Convert.ToChar((byte)1);
Assert.Equal(expectedChar, val.ToChar(null));
sbyte expectedSByte = Convert.ToSByte((byte)1);
Assert.Equal(expectedSByte, val.ToSByte(null));
byte expectedByte = Convert.ToByte((byte)1);
Assert.Equal(expectedByte, val.ToByte(null));
short expectedInt16 = Convert.ToInt16((byte)1);
Assert.Equal(expectedInt16, val.ToInt16(null));
ushort expectedUInt16 = Convert.ToUInt16((byte)1);
Assert.Equal(expectedUInt16, val.ToUInt16(null));
int expectedInt32 = Convert.ToInt32((byte)1);
Assert.Equal(expectedInt32, val.ToInt32(null));
uint expectedUInt32 = Convert.ToUInt32((byte)1);
Assert.Equal(expectedUInt32, val.ToUInt32(null));
long expectedInt64 = Convert.ToInt64((byte)1);
Assert.Equal(expectedInt64, val.ToInt64(null));
ulong expectedUInt64 = Convert.ToUInt64((byte)1);
Assert.Equal(expectedUInt64, val.ToUInt64(null));
float expectedSingle = Convert.ToSingle((byte)1);
Assert.Equal(expectedSingle, val.ToSingle(null));
double expectedDouble = Convert.ToDouble((byte)1);
Assert.Equal(expectedDouble, val.ToDouble(null));
decimal expectedDecimal = Convert.ToDecimal((byte)1);
Assert.Equal(expectedDecimal, val.ToDecimal(null));
Assert.Throws<InvalidCastException>(() => val.ToDateTime(null));
string expectedString = Convert.ToString((byte)1);
Assert.Equal(expectedString, val.ToString(null));
ulong expectedObject = Convert.ToUInt64((byte)1);
Assert.Equal(expectedObject, val.ToType(typeof(ulong), null));
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(0, 1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BothEndian(byte le, byte be, bool expected)
{
var val = new BothUInt8(le, be);
var equalTo = new BothUInt8(1, 1);
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0, 0, false)]
[InlineData(1, 1, true)]
public void Equals_BaseType(byte le, byte be, bool expected)
{
var val = new BothUInt8(le, be);
byte equalTo = 1;
bool actual = val.Equals(equalTo);
Assert.Equal(expected, actual);
}
[Fact]
public void ArithmeticUnaryOperatorsTest()
{
var valA = new BothUInt8(2, 2);
byte expected = 3;
valA++;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
valA = new BothUInt8(2, 2);
expected = 1;
valA--;
Assert.Equal(expected, valA.LittleEndian);
Assert.Equal(expected, valA.BigEndian);
}
[Fact]
public void ArithmeticBinaryOperatorsTest()
{
var valA = new BothUInt8(3, 3);
var valB = new BothUInt8(2, 2);
byte expected = 6;
BothUInt8 actual = valA * valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA / valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA % valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 5;
actual = valA + valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 1;
actual = valA - valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseUnaryOperatorsTest()
{
var valA = new BothUInt8(2, 2);
byte expected = 253;
BothUInt8 actual = ~valA;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void ShiftBinaryOperatorsTest()
{
var valA = new BothUInt8(2, 2);
var valB = new BothUInt8(1, 1);
byte expected = 2 << 1;
BothUInt8 actual = valA << valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >> 1;
actual = valA >> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 2 >>> 1;
actual = valA >>> valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
[Fact]
public void BitwiseBinaryOperatorsTest()
{
var valA = new BothUInt8(3, 3);
var valB = new BothUInt8(2, 2);
byte expected = 3 & 2;
BothUInt8 actual = valA & valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 | 2;
actual = valA | valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
expected = 3 ^ 2;
actual = valA ^ valB;
Assert.Equal(expected, actual.LittleEndian);
Assert.Equal(expected, actual.BigEndian);
}
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.IO;
using SabreTools.IO.Transform;
using Xunit;
namespace SabreTools.IO.Test.Transform
{
public class CombineTests
{
#region Concatenate
[Fact]
public void Concatenate_EmptyList_False()
{
List<string> paths = [];
string output = string.Empty;
bool actual = Combine.Concatenate(paths, output);
Assert.False(actual);
}
[Fact]
public void Concatenate_InvalidOutput_False()
{
List<string> paths = ["a"];
string output = string.Empty;
bool actual = Combine.Concatenate(paths, output);
Assert.False(actual);
}
[Fact]
public void Concatenate_FilledList_True()
{
List<string> paths = [
Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt"),
Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-compress.bin"),
];
string output = Guid.NewGuid().ToString();
bool actual = Combine.Concatenate(paths, output);
Assert.True(actual);
string text = File.ReadAllText(output);
Assert.Equal("This doesn't match anythingThis is just a file that has a known set of hashes to make sure that everything with hashing is still working as anticipated.", text);
File.Delete(output);
}
#endregion
#region Interleave
[Fact]
public void Interleave_EvenNotExists_False()
{
string even = "NOT A REAL PATH";
string odd = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string output = Guid.NewGuid().ToString();
bool actual = Combine.Interleave(even, odd, output, BlockSize.Byte);
Assert.False(actual);
}
[Fact]
public void Interleave_OddNotExists_False()
{
string even = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string odd = "NOT A REAL PATH";
string output = Guid.NewGuid().ToString();
bool actual = Combine.Interleave(even, odd, output, BlockSize.Byte);
Assert.False(actual);
}
[Fact]
public void Interleave_InvalidType_False()
{
string even = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string odd = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string output = Guid.NewGuid().ToString();
bool actual = Combine.Interleave(even, odd, output, (BlockSize)int.MaxValue);
Assert.False(actual);
}
[Theory]
[InlineData(BlockSize.Byte, "TThhiiss ddooeessnn''tt mmaattcchh aannyytthhiinngg")]
[InlineData(BlockSize.Word, "ThThisis d doeoesnsn't't m matatchch a anynyththiningg")]
[InlineData(BlockSize.Dword, "ThisThis doe doesn'tsn't mat match ach anythnythinging")]
[InlineData(BlockSize.Qword, "This doeThis doesn't matsn't match anythch anythinging")]
public void Interleave_SameLength_True(BlockSize type, string expected)
{
string even = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string odd = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string output = Guid.NewGuid().ToString();
bool actual = Combine.Interleave(even, odd, output, type);
Assert.True(actual);
string text = File.ReadAllText(output);
Assert.Equal(expected, text);
File.Delete(output);
}
[Fact]
public void Interleave_DifferentLength_True()
{
string even = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string odd = Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-compress.bin");
string output = Guid.NewGuid().ToString();
bool actual = Combine.Interleave(even, odd, output, BlockSize.Byte);
Assert.True(actual);
string text = File.ReadAllText(output);
Assert.Equal("TThhiiss diose sjnu'stt maa tfcihl ea ntyhtahti nhgas a known set of hashes to make sure that everything with hashing is still working as anticipated.", text);
File.Delete(output);
}
#endregion
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.IO;
using SabreTools.IO.Transform;
using Xunit;
namespace SabreTools.IO.Test.Transform
{
public class SplitTests
{
#region BlockSplit
[Fact]
public void BlockSplit_EmptyFileName_False()
{
string input = string.Empty;
string outputDir = string.Empty;
bool actual = Split.BlockSplit(input, outputDir, BlockSize.Byte);
Assert.False(actual);
}
[Fact]
public void BlockSplit_InvalidFile_False()
{
string input = "INVALID";
string outputDir = string.Empty;
bool actual = Split.BlockSplit(input, outputDir, BlockSize.Byte);
Assert.False(actual);
}
[Fact]
public void BlockSplit_InvalidType_False()
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string outputDir = Guid.NewGuid().ToString();
bool actual = Split.BlockSplit(input, outputDir, (BlockSize)int.MaxValue);
Assert.False(actual);
}
[Theory]
[InlineData(BlockSize.Byte, "Ti os' ac ntig", "hsdentmthayhn")]
[InlineData(BlockSize.Word, "Th dsn mchnyin", "isoe'tat athg")]
[InlineData(BlockSize.Dword, "Thissn'tch aing", " doe matnyth")]
[InlineData(BlockSize.Qword, "This doech anyth", "sn't mating")]
public void BlockSplit_ValidFile_True(BlockSize type, string expectedEven, string expectedOdd)
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string outputDir = Guid.NewGuid().ToString();
bool actual = Split.BlockSplit(input, outputDir, type);
Assert.True(actual);
string baseFilename = Path.GetFileName(input);
string text = File.ReadAllText(Path.Combine(outputDir, $"{baseFilename}.even"));
Assert.Equal(expectedEven, text);
text = File.ReadAllText(Path.Combine(outputDir, $"{baseFilename}.odd"));
Assert.Equal(expectedOdd, text);
File.Delete($"{baseFilename}.even");
File.Delete($"{baseFilename}.odd");
}
#endregion
#region SizeSplit
[Fact]
public void SizeSplit_EmptyFileName_False()
{
string input = string.Empty;
string outputDir = string.Empty;
int size = 1;
bool actual = Split.SizeSplit(input, outputDir, size);
Assert.False(actual);
}
[Fact]
public void SizeSplit_InvalidFile_False()
{
string input = "INVALID";
string outputDir = string.Empty;
int size = 1;
bool actual = Split.SizeSplit(input, outputDir, size);
Assert.False(actual);
}
[Fact]
public void SizeSplit_InvalidSize_False()
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string outputDir = string.Empty;
int size = 0;
bool actual = Split.SizeSplit(input, outputDir, size);
Assert.False(actual);
}
[Fact]
public void SizeSplit_Valid_True()
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string outputDir = Guid.NewGuid().ToString();
int size = 16;
bool actual = Split.SizeSplit(input, outputDir, size);
Assert.True(actual);
Assert.Equal(2, Directory.GetFiles(outputDir).Length);
string baseFilename = Path.GetFileName(input);
string text = File.ReadAllText(Path.Combine(outputDir, $"{baseFilename}.0"));
Assert.Equal("This doesn't mat", text);
text = File.ReadAllText(Path.Combine(outputDir, $"{baseFilename}.1"));
Assert.Equal("ch anything", text);
File.Delete($"{baseFilename}.0");
File.Delete($"{baseFilename}.1");
}
#endregion
}
}

View File

@@ -0,0 +1,76 @@
using System;
using System.IO;
using SabreTools.IO.Extensions;
using SabreTools.IO.Transform;
using Xunit;
namespace SabreTools.IO.Test.Transform
{
public class SwapTests
{
#region Process
[Fact]
public void Process_EmptyFileName_False()
{
string input = string.Empty;
string output = string.Empty;
bool actual = Swap.Process(input, output, Operation.Byteswap);
Assert.False(actual);
}
[Fact]
public void Process_InvalidFile_False()
{
string input = "INVALID";
string output = string.Empty;
bool actual = Swap.Process(input, output, Operation.Byteswap);
Assert.False(actual);
}
[Fact]
public void Process_InvalidType_False()
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string output = Guid.NewGuid().ToString();
bool actual = Swap.Process(input, output, (Operation)int.MaxValue);
Assert.False(actual);
}
[Fact]
public void Process_Valid_True()
{
string input = Path.Combine(Environment.CurrentDirectory, "TestData", "ascii.txt");
string output = Guid.NewGuid().ToString();
// Bitswap
bool actual = Swap.Process(input, output, Operation.Bitswap);
Assert.True(actual);
byte[] actualBytes = File.ReadAllBytes(output);
Assert.True(new byte[] { 0x2A, 0x16, 0x96, 0xCE, 0x04, 0x26, 0xF6, 0xA6, 0xCE, 0x76, 0xE4, 0x2E, 0x04, 0xB6, 0x86, 0x2E, 0xC6, 0x16, 0x04, 0x86, 0x76, 0x9E, 0x2E, 0x16, 0x96, 0x76, 0xE6 }.EqualsExactly(actualBytes));
// Byteswap
actual = Swap.Process(input, output, Operation.Byteswap);
Assert.True(actual);
actualBytes = File.ReadAllBytes(output);
Assert.True(new byte[] { 0x68, 0x54, 0x73, 0x69, 0x64, 0x20, 0x65, 0x6F, 0x6E, 0x73, 0x74, 0x27, 0x6D, 0x20, 0x74, 0x61, 0x68, 0x63, 0x61, 0x20, 0x79, 0x6E, 0x68, 0x74, 0x6E, 0x69, 0x67 }.EqualsExactly(actualBytes));
// Wordswap
actual = Swap.Process(input, output, Operation.Wordswap);
Assert.True(actual);
actualBytes = File.ReadAllBytes(output);
Assert.True(new byte[] { 0x69, 0x73, 0x54, 0x68, 0x6F, 0x65, 0x20, 0x64, 0x27, 0x74, 0x73, 0x6E, 0x61, 0x74, 0x20, 0x6D, 0x20, 0x61, 0x63, 0x68, 0x74, 0x68, 0x6E, 0x79, 0x69, 0x6E, 0x67 }.EqualsExactly(actualBytes));
// WordByteswap
actual = Swap.Process(input, output, Operation.WordByteswap);
Assert.True(actual);
actualBytes = File.ReadAllBytes(output);
Assert.True(new byte[] { 0x73, 0x69, 0x68, 0x54, 0x65, 0x6F, 0x64, 0x20, 0x74, 0x27, 0x6E, 0x73, 0x74, 0x61, 0x6D, 0x20, 0x61, 0x20, 0x68, 0x63, 0x68, 0x74, 0x79, 0x6E, 0x69, 0x6E, 0x67 }.EqualsExactly(actualBytes));
File.Delete(output);
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using SabreTools.Numerics;
namespace SabreTools.IO.Extensions
{
@@ -15,6 +16,24 @@ namespace SabreTools.IO.Extensions
/// TODO: Handle proper negative values for Int24 and Int48
public static class BinaryWriterExtensions
{
/// <inheritdoc cref="BinaryWriter.Write(byte)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothUInt8 value)
{
writer.Write(value.LittleEndian);
writer.Write(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(sbyte)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothInt8 value)
{
writer.Write(value.LittleEndian);
writer.Write(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(byte[])"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, byte[] value)
@@ -39,6 +58,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(short)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothInt16 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(ushort)"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, ushort value)
@@ -48,6 +76,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(ushort)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothUInt16 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
// Half was introduced in net5.0 but doesn't have a BitConverter implementation until net6.0
#if NET6_0_OR_GREATER
/// <inheritdoc cref="BinaryWriter.Write(Half)"/>
@@ -125,6 +162,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(int)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothInt32 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(uint)"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, uint value)
@@ -134,6 +180,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(uint)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothUInt32 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(float)"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, float value)
@@ -208,6 +263,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(long)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothInt64 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(ulong)"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, ulong value)
@@ -217,6 +281,15 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <inheritdoc cref="BinaryWriter.Write(ulong)"/>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this BinaryWriter writer, BothUInt64 value)
{
writer.Write(value.LittleEndian);
writer.WriteBigEndian(value.BigEndian);
return true;
}
/// <inheritdoc cref="BinaryWriter.Write(double)"/>
/// <remarks>Writes in big-endian format</remarks>
public static bool WriteBigEndian(this BinaryWriter writer, double value)
@@ -342,6 +415,14 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedAnsiString(this BinaryWriter writer, string? value)
=> writer.WriteNullTerminatedString(value, Encoding.ASCII);
#if NET5_0_OR_GREATER
/// <summary>
/// Write a null-terminated Latin1 string to the underlying stream
/// </summary>
public static bool WriteNullTerminatedLatin1String(this BinaryWriter writer, string? value)
=> writer.WriteNullTerminatedString(value, Encoding.Latin1);
#endif
/// <summary>
/// Write a null-terminated UTF-8 string to the underlying stream
/// </summary>
@@ -354,6 +435,12 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedUnicodeString(this BinaryWriter writer, string? value)
=> writer.WriteNullTerminatedString(value, Encoding.Unicode);
/// <summary>
/// Write a null-terminated UTF-16 (Unicode) string to the underlying stream
/// </summary>
public static bool WriteNullTerminatedBigEndianUnicodeString(this BinaryWriter writer, string? value)
=> writer.WriteNullTerminatedString(value, Encoding.BigEndianUnicode);
/// <summary>
/// Write a null-terminated UTF-32 string to the underlying stream
/// </summary>
@@ -379,6 +466,27 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
#if NET5_0_OR_GREATER
/// <summary>
/// Write a byte-prefixed Latin1 string to the underlying stream
/// </summary>
public static bool WritePrefixedLatin1String(this BinaryWriter writer, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.Latin1.GetBytes(value);
// Write the length as a byte
writer.Write((byte)value.Length);
// Write the buffer
return WriteFromBuffer(writer, buffer);
}
#endif
/// <summary>
/// Write a ushort-prefixed Unicode string to the underlying stream
/// </summary>
@@ -398,6 +506,25 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(writer, buffer);
}
/// <summary>
/// Write a ushort-prefixed Unicode string to the underlying stream
/// </summary>
public static bool WritePrefixedBigEndianUnicodeString(this BinaryWriter writer, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.BigEndianUnicode.GetBytes(value);
// Write the length as a ushort
writer.Write((ushort)value.Length);
// Write the buffer
return WriteFromBuffer(writer, buffer);
}
/// <summary>
/// Write a <typeparamref name="T"/> to the underlying stream
/// </summary>
@@ -437,7 +564,7 @@ namespace SabreTools.IO.Extensions
{
writer.Write((Half)value);
return true;
}
}
#endif
#if NET7_0_OR_GREATER
else if (type == typeof(Int128))

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using SabreTools.Numerics;
namespace SabreTools.IO.Extensions
{
@@ -20,6 +21,17 @@ namespace SabreTools.IO.Extensions
public static bool Write(this byte[] content, ref int offset, byte value)
=> WriteFromBuffer(content, ref offset, [value]);
/// <summary>
/// Write a UInt8 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothUInt8 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.Write(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt8[] and increment the pointer to an array
/// </summary>
@@ -42,6 +54,17 @@ namespace SabreTools.IO.Extensions
public static bool Write(this byte[] content, ref int offset, sbyte value)
=> WriteFromBuffer(content, ref offset, [(byte)value]);
/// <summary>
/// Write a Int8 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothInt8 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.Write(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a Char and increment the pointer to an array
/// </summary>
@@ -80,6 +103,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a Int16 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothInt16 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt16 and increment the pointer to an array
/// </summary>
@@ -100,6 +134,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a UInt16 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothUInt16 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
// Half was introduced in net5.0 but doesn't have a BitConverter implementation until net6.0
#if NET6_0_OR_GREATER
/// <summary>
@@ -199,6 +244,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a Int32 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothInt32 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt32 and increment the pointer to an array
/// </summary>
@@ -219,6 +275,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a UInt32 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothUInt32 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a Single and increment the pointer to an array
/// </summary>
@@ -315,6 +382,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a Int64 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothInt64 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt64 and increment the pointer to an array
/// </summary>
@@ -335,6 +413,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a UInt64 and increment the pointer to an array
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this byte[] content, ref int offset, BothUInt64 value)
{
bool actual = content.Write(ref offset, value.LittleEndian);
actual &= content.WriteBigEndian(ref offset, value.BigEndian);
return actual;
}
/// <summary>
/// Write a Double and increment the pointer to an array
/// </summary>
@@ -426,7 +515,7 @@ namespace SabreTools.IO.Extensions
public static bool Write(this byte[] content, ref int offset, Int128 value)
{
byte[] buffer = ((BigInteger)value).ToByteArray();
byte[] padded = new byte[16];
Array.Copy(buffer, 0, padded, 16 - buffer.Length, buffer.Length);
return WriteFromBuffer(content, ref offset, padded);
@@ -440,7 +529,7 @@ namespace SabreTools.IO.Extensions
{
byte[] buffer = ((BigInteger)value).ToByteArray();
Array.Reverse(buffer);
byte[] padded = new byte[16];
Array.Copy(buffer, 0, padded, 16 - buffer.Length, buffer.Length);
return WriteFromBuffer(content, ref offset, padded);
@@ -452,7 +541,7 @@ namespace SabreTools.IO.Extensions
public static bool Write(this byte[] content, ref int offset, UInt128 value)
{
byte[] buffer = ((BigInteger)value).ToByteArray();
byte[] padded = new byte[16];
Array.Copy(buffer, 0, padded, 16 - buffer.Length, buffer.Length);
return WriteFromBuffer(content, ref offset, padded);
@@ -466,7 +555,7 @@ namespace SabreTools.IO.Extensions
{
byte[] buffer = ((BigInteger)value).ToByteArray();
Array.Reverse(buffer);
byte[] padded = new byte[16];
Array.Copy(buffer, 0, padded, 16 - buffer.Length, buffer.Length);
return WriteFromBuffer(content, ref offset, padded);
@@ -494,6 +583,14 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedAnsiString(this byte[] content, ref int offset, string? value)
=> content.WriteNullTerminatedString(ref offset, value, Encoding.ASCII);
#if NET5_0_OR_GREATER
/// <summary>
/// Write a null-terminated Latin1 string to the byte array
/// </summary>
public static bool WriteNullTerminatedLatin1String(this byte[] content, ref int offset, string? value)
=> content.WriteNullTerminatedString(ref offset, value, Encoding.Latin1);
#endif
/// <summary>
/// Write a null-terminated UTF-8 string to the byte array
/// </summary>
@@ -506,6 +603,12 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedUnicodeString(this byte[] content, ref int offset, string? value)
=> content.WriteNullTerminatedString(ref offset, value, Encoding.Unicode);
/// <summary>
/// Write a null-terminated UTF-16 (Unicode) string to the byte array
/// </summary>
public static bool WriteNullTerminatedBigEndianUnicodeString(this byte[] content, ref int offset, string? value)
=> content.WriteNullTerminatedString(ref offset, value, Encoding.BigEndianUnicode);
/// <summary>
/// Write a null-terminated UTF-32 string to the byte array
/// </summary>
@@ -532,6 +635,28 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
#if NET5_0_OR_GREATER
/// <summary>
/// Write a byte-prefixed Latin1 string to the byte array
/// </summary>
public static bool WritePrefixedLatin1String(this byte[] content, ref int offset, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.Latin1.GetBytes(value);
// Write the length as a byte
if (!content.Write(ref offset, (byte)value.Length))
return false;
// Write the buffer
return WriteFromBuffer(content, ref offset, buffer);
}
#endif
/// <summary>
/// Write a ushort-prefixed Unicode string to the byte array
/// </summary>
@@ -552,6 +677,26 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a ushort-prefixed Unicode string to the byte array
/// </summary>
public static bool WritePrefixedBigEndianUnicodeString(this byte[] content, ref int offset, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.BigEndianUnicode.GetBytes(value);
// Write the length as a ushort
if (!content.Write(ref offset, (ushort)value.Length))
return false;
// Write the buffer
return WriteFromBuffer(content, ref offset, buffer);
}
/// <summary>
/// Write a <typeparamref name="T"/> to the byte array
/// </summary>

View File

@@ -100,6 +100,14 @@ namespace SabreTools.IO.Extensions
/// <param name="input">Input stream to try seeking on</param>
/// <param name="offset">Optional offset to seek to</param>
public static long SeekIfPossible(this Stream input, long offset = 0)
=> input.SeekIfPossible(offset, offset < 0 ? SeekOrigin.End : SeekOrigin.Begin);
/// <summary>
/// Seek to a specific point in the stream, if possible
/// </summary>
/// <param name="input">Input stream to try seeking on</param>
/// <param name="offset">Optional offset to seek to</param>
public static long SeekIfPossible(this Stream input, long offset, SeekOrigin origin)
{
// If the input is not seekable, just return the current position
if (!input.CanSeek)
@@ -116,10 +124,7 @@ namespace SabreTools.IO.Extensions
// Attempt to seek to the offset
try
{
if (offset < 0)
return input.Seek(offset, SeekOrigin.End);
else
return input.Seek(offset, SeekOrigin.Begin);
return input.Seek(offset, origin);
}
catch
{

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using SabreTools.Numerics;
namespace SabreTools.IO.Extensions
{
@@ -21,6 +22,17 @@ namespace SabreTools.IO.Extensions
public static bool Write(this Stream stream, byte value)
=> WriteFromBuffer(stream, [value]);
/// <summary>
/// Write a UInt8
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothUInt8 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.Write(value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt8[]
/// </summary>
@@ -43,6 +55,17 @@ namespace SabreTools.IO.Extensions
public static bool Write(this Stream stream, sbyte value)
=> WriteFromBuffer(stream, [(byte)value]);
/// <summary>
/// Write a Int8
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothInt8 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.Write(value.BigEndian);
return actual;
}
/// <summary>
/// Write a Char
/// </summary>
@@ -81,6 +104,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a Int16
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothInt16 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt16
/// </summary>
@@ -101,6 +135,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a UInt16
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothUInt16 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
// Half was introduced in net5.0 but doesn't have a BitConverter implementation until net6.0
#if NET6_0_OR_GREATER
/// <summary>
@@ -200,6 +245,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a Int32
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothInt32 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt32
/// </summary>
@@ -220,6 +276,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a UInt32
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothUInt32 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
/// <summary>
/// Write a Single
/// </summary>
@@ -316,6 +383,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a Int64
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothInt64 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
/// <summary>
/// Write a UInt64
/// </summary>
@@ -336,6 +414,17 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a UInt64
/// </summary>
/// <remarks>Writes in both-endian format</remarks>
public static bool WriteBothEndian(this Stream stream, BothUInt64 value)
{
bool actual = stream.Write(value.LittleEndian);
actual &= stream.WriteBigEndian(value.BigEndian);
return actual;
}
/// <summary>
/// Write a Double
/// </summary>
@@ -495,6 +584,14 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedAnsiString(this Stream stream, string? value)
=> stream.WriteNullTerminatedString(value, Encoding.ASCII);
#if NET5_0_OR_GREATER
/// <summary>
/// Write a null-terminated Latin1 string to the stream
/// </summary>
public static bool WriteNullTerminatedLatin1String(this Stream stream, string? value)
=> stream.WriteNullTerminatedString(value, Encoding.Latin1);
#endif
/// <summary>
/// Write a null-terminated UTF-8 string to the stream
/// </summary>
@@ -507,6 +604,12 @@ namespace SabreTools.IO.Extensions
public static bool WriteNullTerminatedUnicodeString(this Stream stream, string? value)
=> stream.WriteNullTerminatedString(value, Encoding.Unicode);
/// <summary>
/// Write a null-terminated UTF-16 (Unicode) string to the stream
/// </summary>
public static bool WriteNullTerminatedBigEndianUnicodeString(this Stream stream, string? value)
=> stream.WriteNullTerminatedString(value, Encoding.BigEndianUnicode);
/// <summary>
/// Write a null-terminated UTF-32 string to the stream
/// </summary>
@@ -533,6 +636,28 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
#if NET5_0_OR_GREATER
//// <summary>
/// Write a byte-prefixed Latin1 string to the stream
/// </summary>
public static bool WritePrefixedLatin1String(this Stream stream, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.Latin1.GetBytes(value);
// Write the length as a byte
if (!stream.Write((byte)value.Length))
return false;
// Write the buffer
return WriteFromBuffer(stream, buffer);
}
#endif
/// <summary>
/// Write a ushort-prefixed Unicode string to the stream
/// </summary>
@@ -553,6 +678,26 @@ namespace SabreTools.IO.Extensions
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a ushort-prefixed Unicode string to the stream
/// </summary>
public static bool WritePrefixedBigEndianUnicodeString(this Stream stream, string? value)
{
// If the value is null
if (value == null)
return false;
// Get the buffer
byte[] buffer = Encoding.BigEndianUnicode.GetBytes(value);
// Write the length as a ushort
if (!stream.Write((ushort)value.Length))
return false;
// Write the buffer
return WriteFromBuffer(stream, buffer);
}
/// <summary>
/// Write a <typeparamref name="T"/> to the stream
/// </summary>

View File

@@ -0,0 +1,234 @@
using System;
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian numeric value
/// </summary>
public abstract class BothEndian<T>(T le, T be) : IComparable, IConvertible, IEquatable<BothEndian<T>>, IEquatable<T>
where T : notnull, IComparable, IConvertible, IEquatable<T>
{
#region Properties
/// <summary>
/// Little-endian representation of the number
/// </summary>
/// <remarks>Value should match <see cref="BigEndian"/></remarks>
public readonly T LittleEndian = le;
/// <summary>
/// Big-endian representation of the number
/// </summary>
/// <remarks>Value should match <see cref="LittleEndian"/></remarks>
public readonly T BigEndian = be;
/// <summary>
/// Indicates if the value is valid
/// </summary>
/// <remarks>
/// Validity of a both-endian value is determined based on if both
/// endianness values match. These values should always match, based
/// on all implementations.
/// </remarks>
public bool IsValid => LittleEndian.Equals(BigEndian);
#endregion
#region Operators
/// <remarks>
/// Returns either <see cref="LittleEndian"/> or <see cref="BigEndian"/>
/// depending on the system endianness.
/// </remarks>
public static implicit operator T(BothEndian<T> val)
=> BitConverter.IsLittleEndian ? val.LittleEndian : val.BigEndian;
public static bool operator ==(BothEndian<T> a, BothEndian<T> b) => a.Equals(b);
public static bool operator !=(BothEndian<T> a, BothEndian<T> b) => !a.Equals(b);
#endregion
#region Object
#if NETCOREAPP
/// <inheritdoc/>
public override bool Equals(object? obj)
{
if (obj is BothEndian<T> be)
return Equals(be);
if (obj is T t)
return Equals(t);
return base.Equals(obj);
}
#else
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is BothEndian<T> be)
return Equals(be);
if (obj is T t)
return Equals(t);
return base.Equals(obj);
}
#endif
/// <inheritdoc/>
public override int GetHashCode() => ((T)this).GetHashCode();
#if NETCOREAPP
/// <inheritdoc/>
public override string? ToString() => ((T)this).ToString();
#else
/// <inheritdoc/>
public override string ToString() => ((T)this).ToString();
#endif
#endregion
#region IComparable
/// <inheritdoc/>
#if NETCOREAPP
public int CompareTo(object? obj) => ((T)this).CompareTo(obj);
#else
public int CompareTo(object obj) => ((T)this).CompareTo(obj);
#endif
#endregion
#region IConvertible
/// <inheritdoc/>
public TypeCode GetTypeCode() => ((T)this).GetTypeCode();
#if NETCOREAPP
/// <inheritdoc/>
public bool ToBoolean(IFormatProvider? provider) => ((T)this).ToBoolean(provider);
/// <inheritdoc/>
public char ToChar(IFormatProvider? provider) => ((T)this).ToChar(provider);
/// <inheritdoc/>
public sbyte ToSByte(IFormatProvider? provider) => ((T)this).ToSByte(provider);
/// <inheritdoc/>
public byte ToByte(IFormatProvider? provider) => ((T)this).ToByte(provider);
/// <inheritdoc/>
public short ToInt16(IFormatProvider? provider) => ((T)this).ToInt16(provider);
/// <inheritdoc/>
public ushort ToUInt16(IFormatProvider? provider) => ((T)this).ToUInt16(provider);
/// <inheritdoc/>
public int ToInt32(IFormatProvider? provider) => ((T)this).ToInt32(provider);
/// <inheritdoc/>
public uint ToUInt32(IFormatProvider? provider) => ((T)this).ToUInt32(provider);
/// <inheritdoc/>
public long ToInt64(IFormatProvider? provider) => ((T)this).ToInt64(provider);
/// <inheritdoc/>
public ulong ToUInt64(IFormatProvider? provider) => ((T)this).ToUInt64(provider);
/// <inheritdoc/>
public float ToSingle(IFormatProvider? provider) => ((T)this).ToSingle(provider);
/// <inheritdoc/>
public double ToDouble(IFormatProvider? provider) => ((T)this).ToDouble(provider);
/// <inheritdoc/>
public decimal ToDecimal(IFormatProvider? provider) => ((T)this).ToDecimal(provider);
/// <inheritdoc/>
public DateTime ToDateTime(IFormatProvider? provider) => ((T)this).ToDateTime(provider);
/// <inheritdoc/>
public string ToString(IFormatProvider? provider) => ((T)this).ToString(provider);
/// <inheritdoc/>
public object ToType(Type conversionType, IFormatProvider? provider) => ((T)this).ToType(conversionType, provider);
#else
/// <inheritdoc/>
public bool ToBoolean(IFormatProvider provider) => ((T)this).ToBoolean(provider);
/// <inheritdoc/>
public char ToChar(IFormatProvider provider) => ((T)this).ToChar(provider);
/// <inheritdoc/>
public sbyte ToSByte(IFormatProvider provider) => ((T)this).ToSByte(provider);
/// <inheritdoc/>
public byte ToByte(IFormatProvider provider) => ((T)this).ToByte(provider);
/// <inheritdoc/>
public short ToInt16(IFormatProvider provider) => ((T)this).ToInt16(provider);
/// <inheritdoc/>
public ushort ToUInt16(IFormatProvider provider) => ((T)this).ToUInt16(provider);
/// <inheritdoc/>
public int ToInt32(IFormatProvider provider) => ((T)this).ToInt32(provider);
/// <inheritdoc/>
public uint ToUInt32(IFormatProvider provider) => ((T)this).ToUInt32(provider);
/// <inheritdoc/>
public long ToInt64(IFormatProvider provider) => ((T)this).ToInt64(provider);
/// <inheritdoc/>
public ulong ToUInt64(IFormatProvider provider) => ((T)this).ToUInt64(provider);
/// <inheritdoc/>
public float ToSingle(IFormatProvider provider) => ((T)this).ToSingle(provider);
/// <inheritdoc/>
public double ToDouble(IFormatProvider provider) => ((T)this).ToDouble(provider);
/// <inheritdoc/>
public decimal ToDecimal(IFormatProvider provider) => ((T)this).ToDecimal(provider);
/// <inheritdoc/>
public DateTime ToDateTime(IFormatProvider provider) => ((T)this).ToDateTime(provider);
/// <inheritdoc/>
public string ToString(IFormatProvider provider) => ((T)this).ToString(provider);
/// <inheritdoc/>
public object ToType(Type conversionType, IFormatProvider provider) => ((T)this).ToType(conversionType, provider);
#endif
#endregion
#region IEquatable
#if NETCOREAPP
/// <inheritdoc/>
public bool Equals(BothEndian<T>? other)
{
if (other is null)
return false;
return LittleEndian.Equals(other.LittleEndian) && BigEndian.Equals(other.BigEndian);
}
/// <inheritdoc/>
public bool Equals(T? other) => ((T)this).Equals(other);
#else
/// <inheritdoc/>
public bool Equals(BothEndian<T> other)
=> LittleEndian.Equals(other.LittleEndian) && BigEndian.Equals(other.BigEndian);
/// <inheritdoc/>
public bool Equals(T other) => ((T)this).Equals(other);
#endif
#endregion
}
}

View File

@@ -0,0 +1,143 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 16-bit signed value
/// </summary>
public sealed class BothInt16(short le, short be) : BothEndian<short>(le, be)
{
public static implicit operator BothInt16(short val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothInt16 operator ++(BothInt16 a)
{
short le = (short)(a.LittleEndian + 1);
short be = (short)(a.BigEndian + 1);
return new BothInt16(le, be);
}
public static BothInt16 operator --(BothInt16 a)
{
short le = (short)(a.LittleEndian - 1);
short be = (short)(a.BigEndian - 1);
return new BothInt16(le, be);
}
public static BothInt16 operator +(BothInt16 a)
{
short le = (short)(+a.LittleEndian);
short be = (short)(+a.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator -(BothInt16 a)
{
short le = (short)(-a.LittleEndian);
short be = (short)(-a.BigEndian);
return new BothInt16(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothInt16 operator *(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian * b.LittleEndian);
short be = (short)(a.BigEndian * b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator /(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian / b.LittleEndian);
short be = (short)(a.BigEndian / b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator %(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian % b.LittleEndian);
short be = (short)(a.BigEndian % b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator +(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian + b.LittleEndian);
short be = (short)(a.BigEndian + b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator -(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian - b.LittleEndian);
short be = (short)(a.BigEndian - b.BigEndian);
return new BothInt16(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothInt16 operator ~(BothInt16 a)
{
short le = (short)(~a.LittleEndian);
short be = (short)(~a.BigEndian);
return new BothInt16(le, be);
}
#endregion
#region Shift Binary Operators
public static BothInt16 operator <<(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian << b.LittleEndian);
short be = (short)(a.BigEndian << b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator >>(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian >> b.LittleEndian);
short be = (short)(a.BigEndian >> b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator >>>(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian >>> b.LittleEndian);
short be = (short)(a.BigEndian >>> b.BigEndian);
return new BothInt16(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothInt16 operator &(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian & b.LittleEndian);
short be = (short)(a.BigEndian & b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator |(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian | b.LittleEndian);
short be = (short)(a.BigEndian | b.BigEndian);
return new BothInt16(le, be);
}
public static BothInt16 operator ^(BothInt16 a, BothInt16 b)
{
short le = (short)(a.LittleEndian ^ b.LittleEndian);
short be = (short)(a.BigEndian ^ b.BigEndian);
return new BothInt16(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,143 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 32-bit signed value
/// </summary>
public sealed class BothInt32(int le, int be) : BothEndian<int>(le, be)
{
public static implicit operator BothInt32(int val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothInt32 operator ++(BothInt32 a)
{
int le = (int)(a.LittleEndian + 1);
int be = (int)(a.BigEndian + 1);
return new BothInt32(le, be);
}
public static BothInt32 operator --(BothInt32 a)
{
int le = (int)(a.LittleEndian - 1);
int be = (int)(a.BigEndian - 1);
return new BothInt32(le, be);
}
public static BothInt32 operator +(BothInt32 a)
{
int le = (int)(+a.LittleEndian);
int be = (int)(+a.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator -(BothInt32 a)
{
int le = (int)(-a.LittleEndian);
int be = (int)(-a.BigEndian);
return new BothInt32(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothInt32 operator *(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian * b.LittleEndian);
int be = (int)(a.BigEndian * b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator /(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian / b.LittleEndian);
int be = (int)(a.BigEndian / b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator %(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian % b.LittleEndian);
int be = (int)(a.BigEndian % b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator +(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian + b.LittleEndian);
int be = (int)(a.BigEndian + b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator -(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian - b.LittleEndian);
int be = (int)(a.BigEndian - b.BigEndian);
return new BothInt32(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothInt32 operator ~(BothInt32 a)
{
int le = (int)(~a.LittleEndian);
int be = (int)(~a.BigEndian);
return new BothInt32(le, be);
}
#endregion
#region Shift Binary Operators
public static BothInt32 operator <<(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian << b.LittleEndian);
int be = (int)(a.BigEndian << b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator >>(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian >> b.LittleEndian);
int be = (int)(a.BigEndian >> b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator >>>(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian >>> b.LittleEndian);
int be = (int)(a.BigEndian >>> b.BigEndian);
return new BothInt32(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothInt32 operator &(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian & b.LittleEndian);
int be = (int)(a.BigEndian & b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator |(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian | b.LittleEndian);
int be = (int)(a.BigEndian | b.BigEndian);
return new BothInt32(le, be);
}
public static BothInt32 operator ^(BothInt32 a, BothInt32 b)
{
int le = (int)(a.LittleEndian ^ b.LittleEndian);
int be = (int)(a.BigEndian ^ b.BigEndian);
return new BothInt32(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,143 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 64-bit signed value
/// </summary>
public sealed class BothInt64(long le, long be) : BothEndian<long>(le, be)
{
public static implicit operator BothInt64(long val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothInt64 operator ++(BothInt64 a)
{
long le = (long)(a.LittleEndian + 1);
long be = (long)(a.BigEndian + 1);
return new BothInt64(le, be);
}
public static BothInt64 operator --(BothInt64 a)
{
long le = (long)(a.LittleEndian - 1);
long be = (long)(a.BigEndian - 1);
return new BothInt64(le, be);
}
public static BothInt64 operator +(BothInt64 a)
{
long le = (long)(+a.LittleEndian);
long be = (long)(+a.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator -(BothInt64 a)
{
long le = (long)(-a.LittleEndian);
long be = (long)(-a.BigEndian);
return new BothInt64(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothInt64 operator *(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian * b.LittleEndian);
long be = (long)(a.BigEndian * b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator /(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian / b.LittleEndian);
long be = (long)(a.BigEndian / b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator %(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian % b.LittleEndian);
long be = (long)(a.BigEndian % b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator +(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian + b.LittleEndian);
long be = (long)(a.BigEndian + b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator -(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian - b.LittleEndian);
long be = (long)(a.BigEndian - b.BigEndian);
return new BothInt64(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothInt64 operator ~(BothInt64 a)
{
long le = (long)(~a.LittleEndian);
long be = (long)(~a.BigEndian);
return new BothInt64(le, be);
}
#endregion
#region Shift Binary Operators
public static BothInt64 operator <<(BothInt64 a, BothInt32 b)
{
long le = (long)(a.LittleEndian << b.LittleEndian);
long be = (long)(a.BigEndian << b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator >>(BothInt64 a, BothInt32 b)
{
long le = (long)(a.LittleEndian >> b.LittleEndian);
long be = (long)(a.BigEndian >> b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator >>>(BothInt64 a, BothInt32 b)
{
long le = (long)(a.LittleEndian >>> b.LittleEndian);
long be = (long)(a.BigEndian >>> b.BigEndian);
return new BothInt64(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothInt64 operator &(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian & b.LittleEndian);
long be = (long)(a.BigEndian & b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator |(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian | b.LittleEndian);
long be = (long)(a.BigEndian | b.BigEndian);
return new BothInt64(le, be);
}
public static BothInt64 operator ^(BothInt64 a, BothInt64 b)
{
long le = (long)(a.LittleEndian ^ b.LittleEndian);
long be = (long)(a.BigEndian ^ b.BigEndian);
return new BothInt64(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,143 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 8-bit signed value
/// </summary>
public sealed class BothInt8(sbyte le, sbyte be) : BothEndian<sbyte>(le, be)
{
public static implicit operator BothInt8(sbyte val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothInt8 operator ++(BothInt8 a)
{
sbyte le = (sbyte)(a.LittleEndian + 1);
sbyte be = (sbyte)(a.BigEndian + 1);
return new BothInt8(le, be);
}
public static BothInt8 operator --(BothInt8 a)
{
sbyte le = (sbyte)(a.LittleEndian - 1);
sbyte be = (sbyte)(a.BigEndian - 1);
return new BothInt8(le, be);
}
public static BothInt8 operator +(BothInt8 a)
{
sbyte le = (sbyte)(+a.LittleEndian);
sbyte be = (sbyte)(+a.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator -(BothInt8 a)
{
sbyte le = (sbyte)(-a.LittleEndian);
sbyte be = (sbyte)(-a.BigEndian);
return new BothInt8(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothInt8 operator *(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian * b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian * b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator /(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian / b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian / b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator %(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian % b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian % b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator +(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian + b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian + b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator -(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian - b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian - b.BigEndian);
return new BothInt8(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothInt8 operator ~(BothInt8 a)
{
sbyte le = (sbyte)(~a.LittleEndian);
sbyte be = (sbyte)(~a.BigEndian);
return new BothInt8(le, be);
}
#endregion
#region Shift Binary Operators
public static BothInt8 operator <<(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian << b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian << b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator >>(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian >> b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian >> b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator >>>(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian >>> b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian >>> b.BigEndian);
return new BothInt8(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothInt8 operator &(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian & b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian & b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator |(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian | b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian | b.BigEndian);
return new BothInt8(le, be);
}
public static BothInt8 operator ^(BothInt8 a, BothInt8 b)
{
sbyte le = (sbyte)(a.LittleEndian ^ b.LittleEndian);
sbyte be = (sbyte)(a.BigEndian ^ b.BigEndian);
return new BothInt8(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,129 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 16-bit unsigned value
/// </summary>
public sealed class BothUInt16(ushort le, ushort be) : BothEndian<ushort>(le, be)
{
public static implicit operator BothUInt16(ushort val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothUInt16 operator ++(BothUInt16 a)
{
ushort le = (ushort)(a.LittleEndian + 1);
ushort be = (ushort)(a.BigEndian + 1);
return new BothUInt16(le, be);
}
public static BothUInt16 operator --(BothUInt16 a)
{
ushort le = (ushort)(a.LittleEndian - 1);
ushort be = (ushort)(a.BigEndian - 1);
return new BothUInt16(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothUInt16 operator *(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian * b.LittleEndian);
ushort be = (ushort)(a.BigEndian * b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator /(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian / b.LittleEndian);
ushort be = (ushort)(a.BigEndian / b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator %(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian % b.LittleEndian);
ushort be = (ushort)(a.BigEndian % b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator +(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian + b.LittleEndian);
ushort be = (ushort)(a.BigEndian + b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator -(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian - b.LittleEndian);
ushort be = (ushort)(a.BigEndian - b.BigEndian);
return new BothUInt16(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothUInt16 operator ~(BothUInt16 a)
{
ushort le = (ushort)(~a.LittleEndian);
ushort be = (ushort)(~a.BigEndian);
return new BothUInt16(le, be);
}
#endregion
#region Shift Binary Operators
public static BothUInt16 operator <<(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian << b.LittleEndian);
ushort be = (ushort)(a.BigEndian << b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator >>(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian >> b.LittleEndian);
ushort be = (ushort)(a.BigEndian >> b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator >>>(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian >>> b.LittleEndian);
ushort be = (ushort)(a.BigEndian >>> b.BigEndian);
return new BothUInt16(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothUInt16 operator &(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian & b.LittleEndian);
ushort be = (ushort)(a.BigEndian & b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator |(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian | b.LittleEndian);
ushort be = (ushort)(a.BigEndian | b.BigEndian);
return new BothUInt16(le, be);
}
public static BothUInt16 operator ^(BothUInt16 a, BothUInt16 b)
{
ushort le = (ushort)(a.LittleEndian ^ b.LittleEndian);
ushort be = (ushort)(a.BigEndian ^ b.BigEndian);
return new BothUInt16(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,129 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 32-bit unsigned value
/// </summary>
public sealed class BothUInt32(uint le, uint be) : BothEndian<uint>(le, be)
{
public static implicit operator BothUInt32(uint val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothUInt32 operator ++(BothUInt32 a)
{
uint le = (uint)(a.LittleEndian + 1);
uint be = (uint)(a.BigEndian + 1);
return new BothUInt32(le, be);
}
public static BothUInt32 operator --(BothUInt32 a)
{
uint le = (uint)(a.LittleEndian - 1);
uint be = (uint)(a.BigEndian - 1);
return new BothUInt32(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothUInt32 operator *(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian * b.LittleEndian);
uint be = (uint)(a.BigEndian * b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator /(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian / b.LittleEndian);
uint be = (uint)(a.BigEndian / b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator %(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian % b.LittleEndian);
uint be = (uint)(a.BigEndian % b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator +(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian + b.LittleEndian);
uint be = (uint)(a.BigEndian + b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator -(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian - b.LittleEndian);
uint be = (uint)(a.BigEndian - b.BigEndian);
return new BothUInt32(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothUInt32 operator ~(BothUInt32 a)
{
uint le = (uint)(~a.LittleEndian);
uint be = (uint)(~a.BigEndian);
return new BothUInt32(le, be);
}
#endregion
#region Shift Binary Operators
public static BothUInt32 operator <<(BothUInt32 a, BothInt32 b)
{
uint le = (uint)(a.LittleEndian << b.LittleEndian);
uint be = (uint)(a.BigEndian << b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator >>(BothUInt32 a, BothInt32 b)
{
uint le = (uint)(a.LittleEndian >> b.LittleEndian);
uint be = (uint)(a.BigEndian >> b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator >>>(BothUInt32 a, BothInt32 b)
{
uint le = (uint)(a.LittleEndian >>> b.LittleEndian);
uint be = (uint)(a.BigEndian >>> b.BigEndian);
return new BothUInt32(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothUInt32 operator &(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian & b.LittleEndian);
uint be = (uint)(a.BigEndian & b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator |(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian | b.LittleEndian);
uint be = (uint)(a.BigEndian | b.BigEndian);
return new BothUInt32(le, be);
}
public static BothUInt32 operator ^(BothUInt32 a, BothUInt32 b)
{
uint le = (uint)(a.LittleEndian ^ b.LittleEndian);
uint be = (uint)(a.BigEndian ^ b.BigEndian);
return new BothUInt32(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,129 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 64-bit unsigned value
/// </summary>
public sealed class BothUInt64(ulong le, ulong be) : BothEndian<ulong>(le, be)
{
public static implicit operator BothUInt64(ulong val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothUInt64 operator ++(BothUInt64 a)
{
ulong le = (ulong)(a.LittleEndian + 1);
ulong be = (ulong)(a.BigEndian + 1);
return new BothUInt64(le, be);
}
public static BothUInt64 operator --(BothUInt64 a)
{
ulong le = (ulong)(a.LittleEndian - 1);
ulong be = (ulong)(a.BigEndian - 1);
return new BothUInt64(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothUInt64 operator *(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian * b.LittleEndian);
ulong be = (ulong)(a.BigEndian * b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator /(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian / b.LittleEndian);
ulong be = (ulong)(a.BigEndian / b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator %(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian % b.LittleEndian);
ulong be = (ulong)(a.BigEndian % b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator +(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian + b.LittleEndian);
ulong be = (ulong)(a.BigEndian + b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator -(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian - b.LittleEndian);
ulong be = (ulong)(a.BigEndian - b.BigEndian);
return new BothUInt64(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothUInt64 operator ~(BothUInt64 a)
{
ulong le = (ulong)(~a.LittleEndian);
ulong be = (ulong)(~a.BigEndian);
return new BothUInt64(le, be);
}
#endregion
#region Shift Binary Operators
public static BothUInt64 operator <<(BothUInt64 a, BothInt32 b)
{
ulong le = (ulong)(a.LittleEndian << b.LittleEndian);
ulong be = (ulong)(a.BigEndian << b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator >>(BothUInt64 a, BothInt32 b)
{
ulong le = (ulong)(a.LittleEndian >> b.LittleEndian);
ulong be = (ulong)(a.BigEndian >> b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator >>>(BothUInt64 a, BothInt32 b)
{
ulong le = (ulong)(a.LittleEndian >>> b.LittleEndian);
ulong be = (ulong)(a.BigEndian >>> b.BigEndian);
return new BothUInt64(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothUInt64 operator &(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian & b.LittleEndian);
ulong be = (ulong)(a.BigEndian & b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator |(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian | b.LittleEndian);
ulong be = (ulong)(a.BigEndian | b.BigEndian);
return new BothUInt64(le, be);
}
public static BothUInt64 operator ^(BothUInt64 a, BothUInt64 b)
{
ulong le = (ulong)(a.LittleEndian ^ b.LittleEndian);
ulong be = (ulong)(a.BigEndian ^ b.BigEndian);
return new BothUInt64(le, be);
}
#endregion
}
}

View File

@@ -0,0 +1,129 @@
namespace SabreTools.Numerics
{
/// <summary>
/// Both-endian 8-bit unsigned value
/// </summary>
public sealed class BothUInt8(byte le, byte be) : BothEndian<byte>(le, be)
{
public static implicit operator BothUInt8(byte val)
=> new(val, val);
#region Arithmetic Unary Operators
public static BothUInt8 operator ++(BothUInt8 a)
{
byte le = (byte)(a.LittleEndian + 1);
byte be = (byte)(a.BigEndian + 1);
return new BothUInt8(le, be);
}
public static BothUInt8 operator --(BothUInt8 a)
{
byte le = (byte)(a.LittleEndian - 1);
byte be = (byte)(a.BigEndian - 1);
return new BothUInt8(le, be);
}
#endregion
#region Arithmetic Binary Operators
public static BothUInt8 operator *(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian * b.LittleEndian);
byte be = (byte)(a.BigEndian * b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator /(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian / b.LittleEndian);
byte be = (byte)(a.BigEndian / b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator %(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian % b.LittleEndian);
byte be = (byte)(a.BigEndian % b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator +(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian + b.LittleEndian);
byte be = (byte)(a.BigEndian + b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator -(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian - b.LittleEndian);
byte be = (byte)(a.BigEndian - b.BigEndian);
return new BothUInt8(le, be);
}
#endregion
#region Bitwise Unary Operators
public static BothUInt8 operator ~(BothUInt8 a)
{
byte le = (byte)(~a.LittleEndian);
byte be = (byte)(~a.BigEndian);
return new BothUInt8(le, be);
}
#endregion
#region Shift Binary Operators
public static BothUInt8 operator <<(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian << b.LittleEndian);
byte be = (byte)(a.BigEndian << b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator >>(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian >> b.LittleEndian);
byte be = (byte)(a.BigEndian >> b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator >>>(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian >>> b.LittleEndian);
byte be = (byte)(a.BigEndian >>> b.BigEndian);
return new BothUInt8(le, be);
}
#endregion
#region Bitwise Binary Operators
public static BothUInt8 operator &(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian & b.LittleEndian);
byte be = (byte)(a.BigEndian & b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator |(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian | b.LittleEndian);
byte be = (byte)(a.BigEndian | b.BigEndian);
return new BothUInt8(le, be);
}
public static BothUInt8 operator ^(BothUInt8 a, BothUInt8 b)
{
byte le = (byte)(a.LittleEndian ^ b.LittleEndian);
byte be = (byte)(a.BigEndian ^ b.BigEndian);
return new BothUInt8(le, be);
}
#endregion
}
}

View File

@@ -11,7 +11,7 @@
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.7.6</Version>
<Version>1.8.0</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>

View File

@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace SabreTools.IO.Transform
{
/// <summary>
/// Helpers to combine inputs
/// </summary>
public static class Combine
{
/// <summary>
/// Concatenate all files in the order provided, if possible
/// </summary>
/// <param name="paths">List of paths to combine</param>
/// <param name="output">Path to the output file</param>
/// <returns>True if the files were concatenated successfully, false otherwise</returns>
public static bool Concatenate(List<string> paths, string output)
{
// If the path list is empty
if (paths.Count == 0)
return false;
// If the output filename is invalid
if (string.IsNullOrEmpty(output))
return false;
try
{
// Try to build the new output file
using var ofs = File.Open(output, FileMode.Create, FileAccess.Write, FileShare.None);
for (int i = 0; i < paths.Count; i++)
{
// Get the next file
string next = paths[i];
if (!File.Exists(next))
break;
// Copy the next input to the output
using var ifs = File.Open(next, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Write in blocks
int read = 0;
do
{
byte[] buffer = new byte[3 * 1024 * 1024];
read = ifs.Read(buffer, 0, buffer.Length);
if (read == 0)
break;
ofs.Write(buffer, 0, read);
ofs.Flush();
} while (read > 0);
}
return true;
}
catch
{
// Absorb the exception right now
return false;
}
}
/// <summary>
/// Interleave two files into a single output
/// </summary>
/// <param name="even">First file to interleave</param>
/// <param name="odd">Second file to interleave</param>
/// <param name="output">Path to the output file</param>
/// <param name="type"><see cref="BlockSize"> representing how to process the inputs</param>
/// <returns>True if the files were interleaved successfully, false otherwise</returns>
public static bool Interleave(string even, string odd, string output, BlockSize type)
{
// If either file does not exist
if (!File.Exists(even) || !File.Exists(odd))
return false;
try
{
// Get the input streams
using var evenStream = File.Open(even, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var oddStream = File.Open(odd, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Interleave the streams
using var interleaved = Interleave(evenStream, oddStream, type);
if (interleaved == null)
return false;
// Open the output file
using var outputStream = File.Open(output, FileMode.Create, FileAccess.Write, FileShare.None);
// Write the interleaved data
interleaved.CopyTo(outputStream);
outputStream.Flush();
}
catch
{
// Absorb all errors for now
return false;
}
return true;
}
/// <summary>
/// Interleave two streams into a single output
/// </summary>
/// <param name="even">First stream to interleave</param>
/// <param name="odd">Second stream to interleave</param>
/// <param name="output">Path to the output file</param>
/// <param name="type"><see cref="BlockSize"> representing how to process the inputs</param>
/// <returns>A filled stream on success, null otherwise</returns>
public static Stream? Interleave(Stream even, Stream odd, BlockSize type)
{
// If either stream is unreadable
if (!even.CanRead || !odd.CanRead)
return null;
// Get the number of bytes to process
int byteCount = type switch
{
BlockSize.Byte => 1,
BlockSize.Word => 2,
BlockSize.Dword => 4,
BlockSize.Qword => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type)),
};
try
{
// Create an output stream
var outputStream = new MemoryStream();
// Alternate between inputs during reading
bool useEven = true;
while (even.Position < even.Length || odd.Position < odd.Length)
{
byte[] read = new byte[byteCount];
int actual = (useEven ? even : odd).Read(read, 0, byteCount);
outputStream.Write(read, 0, actual);
outputStream.Flush();
useEven = !useEven;
}
outputStream.Seek(0, SeekOrigin.Begin);
return outputStream;
}
catch
{
// Absorb all errors for now
return null;
}
}
}
}

View File

@@ -0,0 +1,54 @@
namespace SabreTools.IO.Transform
{
/// <summary>
/// Determines the block size of an operation
/// </summary>
public enum BlockSize
{
/// <summary>
/// 1 byte blocks
/// </summary>
Byte = 1,
/// <summary>
/// 2 byte blocks
/// </summary>
Word = 2,
/// <summary>
/// 4 byte blocks
/// </summary>
Dword = 4,
/// <summary>
/// 8 byte blocks
/// </summary>
Qword = 8,
}
/// <summary>
/// Determines the swapping operation
/// </summary>
public enum Operation
{
/// <summary>
/// Reverse endianness of each byte
/// </summary>
Bitswap,
/// <summary>
/// Swap every 1 byte
/// </summary>
Byteswap,
/// <summary>
/// Swap every 2 bytes
/// </summary>
Wordswap,
/// <summary>
/// Swap every 2 bytes and bytes within the 2 bytes
/// </summary>
WordByteswap,
}
}

View File

@@ -0,0 +1,177 @@
using System;
using System.IO;
namespace SabreTools.IO.Transform
{
/// <summary>
/// Helpers to split inputs
/// </summary>
public static class Split
{
/// <summary>
/// Split an input file into two outputs
/// </summary>
/// <param name="input">Input file name</param>
/// <param name="outputDir">Path to the output directory</param>
/// <param name="type"><see cref="BlockSize"> representing how to process the inputs</param>
/// <returns>True if the file could be split, false otherwise</returns>
public static bool BlockSplit(string input, string? outputDir, BlockSize type)
{
// If the file does not exist
if (!File.Exists(input))
return false;
try
{
// Get the input stream
using var inputStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Split the stream
if (!BlockSplit(inputStream, type, out Stream? evenStream, out Stream? oddStream))
return false;
else if (evenStream == null || oddStream == null)
return false;
// Get the base filename for output files
outputDir ??= Path.GetDirectoryName(input);
string baseFilename = Path.GetFileName(input);
if (!string.IsNullOrEmpty(outputDir))
baseFilename = Path.Combine(outputDir, baseFilename);
// Create the output directory, if possible
if (outputDir != null && !Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);
// Open the output files
using var outEvenStream = File.Open($"{baseFilename}.even", FileMode.Create, FileAccess.Write, FileShare.None);
using var outOddStream = File.Open($"{baseFilename}.odd", FileMode.Create, FileAccess.Write, FileShare.None);
// Write the split data
evenStream.CopyTo(outEvenStream);
outEvenStream.Flush();
oddStream.CopyTo(outOddStream);
outOddStream.Flush();
}
catch
{
// Absorb all errors for now
return false;
}
return true;
}
/// <summary>
/// Split an input stream into two output streams
/// </summary>
/// <param name="input">Input stream</param>
/// <param name="type"><see cref="BlockSize"> representing how to process the inputs</param>
/// <param name="even">Even block output stream on success, null otherwise</param>
/// <param name="odd">Odd block output stream on success, null otherwise</param>
/// <returns>True if the stream could be split, false otherwise</returns>
public static bool BlockSplit(Stream input, BlockSize type, out Stream? even, out Stream? odd)
{
// Set default values for the outputs
even = null;
odd = null;
// If the stream is unreadable
if (!input.CanRead)
return false;
// Get the number of bytes to process
int byteCount = type switch
{
BlockSize.Byte => 1,
BlockSize.Word => 2,
BlockSize.Dword => 4,
BlockSize.Qword => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type)),
};
try
{
// Create the output streams
even = new MemoryStream();
odd = new MemoryStream();
// Alternate between inputs during reading
bool useEven = true;
while (input.Position < input.Length)
{
byte[] read = new byte[byteCount];
int actual = input.Read(read, 0, byteCount);
(useEven ? even : odd).Write(read, 0, actual);
(useEven ? even : odd).Flush();
useEven = !useEven;
}
even.Seek(0, SeekOrigin.Begin);
odd.Seek(0, SeekOrigin.Begin);
return true;
}
catch
{
// Absorb all errors for now
even = null;
odd = null;
return false;
}
}
/// <summary>
/// Split an input file into files of up to <paramref name="size"/> bytes
/// </summary>
/// <param name="input">Input file name</param>
/// <param name="outputDir">Path to the output directory</param>
/// <param name="size">Maximum number of bytes to split on</param>
/// <returns>True if the file could be split, false otherwise</returns>
public static bool SizeSplit(string input, string? outputDir, int size)
{
// If the file does not exist
if (!File.Exists(input))
return false;
// If the size is invalid
if (size <= 0)
return false;
try
{
// Get the input stream
using var inputStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Get the base filename for output files
outputDir ??= Path.GetDirectoryName(input);
string baseFilename = Path.GetFileName(input);
if (!string.IsNullOrEmpty(outputDir))
baseFilename = Path.Combine(outputDir, baseFilename);
// Create the output directory, if possible
if (outputDir != null && !Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);
// Loop while there is data left
int part = 0;
while (inputStream.Position < inputStream.Length)
{
// Create the next output file
using var partStream = File.Open($"{baseFilename}.{part++}", FileMode.Create, FileAccess.Write, FileShare.None);
// Process the next block of data
byte[] data = new byte[size];
int actual = inputStream.Read(data, 0, size);
partStream.Write(data, 0, actual);
partStream.Flush();
}
return true;
}
catch
{
// Absorb all errors for now
return false;
}
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.IO;
using SabreTools.IO.Extensions;
namespace SabreTools.IO.Transform
{
/// <summary>
/// Helpers to perform swapping operations
/// </summary>
public static class Swap
{
/// <summary>
/// Transform an input file using the given rule
/// </summary>
/// <param name="input">Input file name</param>
/// <param name="output">Output file name</param>
/// <param name="operation">Transform operation to carry out</param>
/// <returns>True if the file was transformed properly, false otherwise</returns>
public static bool Process(string input, string output, Operation operation)
{
// If the file does not exist
if (!File.Exists(input))
return false;
// Create the output directory if it doesn't already
string? outputDirectory = Path.GetDirectoryName(Path.GetFullPath(output));
if (outputDirectory != null && !Directory.Exists(outputDirectory))
Directory.CreateDirectory(outputDirectory);
try
{
// Get the input stream
using var inputStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Transform the stream
var transformed = Process(inputStream, operation);
if (transformed == null)
return false;
// Open the output file
using var outputStream = File.Open(output, FileMode.Create, FileAccess.Write, FileShare.None);
// Write the transformed data
transformed.CopyTo(outputStream);
outputStream.Flush();
}
catch
{
// Absorb all errors for now
return false;
}
return true;
}
/// <summary>
/// Transform an input stream using the given rule
/// </summary>
/// <param name="input">Input stream</param>
/// <param name="operation">Transform operation to carry out</param>
/// <returns>True if the file was transformed properly, false otherwise</returns>
public static Stream? Process(Stream input, Operation operation)
{
// If the stream is unreadable
if (!input.CanRead)
return null;
// If the operation is not defined
if (!Enum.IsDefined(typeof(Operation), operation))
return null;
try
{
// Create an output stream
var output = new MemoryStream();
// Determine the cutoff boundary for the operation
long endBoundary = operation switch
{
Operation.Bitswap => input.Length,
Operation.Byteswap => input.Length - (input.Length % 2),
Operation.Wordswap => input.Length - (input.Length % 4),
Operation.WordByteswap => input.Length - (input.Length % 4),
_ => throw new ArgumentOutOfRangeException(nameof(operation)),
};
// Loop over the input and process in blocks
byte[] buffer = new byte[4];
int pos = 0;
while (input.Position < endBoundary)
{
byte b = input.ReadByteValue();
switch (operation)
{
case Operation.Bitswap:
uint r = b;
int s = 7;
for (b >>= 1; b != 0; b >>= 1)
{
r <<= 1;
r |= (byte)(b & 1);
s--;
}
r <<= s;
buffer[pos] = (byte)r;
break;
case Operation.Byteswap:
if (pos % 2 == 1)
buffer[pos - 1] = b;
else
buffer[pos + 1] = b;
break;
case Operation.Wordswap:
buffer[(pos + 2) % 4] = b;
break;
case Operation.WordByteswap:
buffer[3 - pos] = b;
break;
default:
buffer[pos] = b;
break;
}
// Set the buffer position to default write to
pos = (pos + 1) % 4;
// If the buffer pointer has been reset
if (pos == 0)
{
output.Write(buffer);
output.Flush();
buffer = new byte[4];
}
}
// If there's anything more in the buffer
for (int i = 0; i < pos; i++)
{
output.Write(buffer[i]);
}
// If the stream still has data
if (input.Position < input.Length)
{
byte[] bytes = input.ReadBytes((int)(input.Length - input.Position));
output.Write(bytes);
output.Flush();
}
output.Seek(0, SeekOrigin.Begin);
return output;
}
catch
{
// Absorb all errors for now
return null;
}
}
}
}