mirror of
https://github.com/SabreTools/SabreTools.IO.git
synced 2026-02-12 21:32:16 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16b238539b | ||
|
|
68f49eeb48 | ||
|
|
c5ecd41a8f | ||
|
|
9ab9dd4ff8 | ||
|
|
867c8d11da | ||
|
|
65dbb7a31a | ||
|
|
1eaf7954fe | ||
|
|
a602a07514 | ||
|
|
466b0e90e7 | ||
|
|
abdf50c9e0 | ||
|
|
12341ba6aa | ||
|
|
70b78f861c | ||
|
|
5b306ce9e8 | ||
|
|
2b6fc200e2 | ||
|
|
7c63f44c75 | ||
|
|
edd3e6eef2 | ||
|
|
244b7411d4 | ||
|
|
fb60f1fed5 | ||
|
|
8f06bf5859 | ||
|
|
2c5d7ad56b | ||
|
|
46996c10e5 | ||
|
|
7491821679 | ||
|
|
8fe404e732 | ||
|
|
793168fbe5 | ||
|
|
67b6118cc1 | ||
|
|
b12d122721 | ||
|
|
20f1679557 | ||
|
|
7ccedbeac5 | ||
|
|
72910cc1c0 | ||
|
|
8f4ea0da16 | ||
|
|
eb4975b261 | ||
|
|
995c19d903 | ||
|
|
f0fe9af467 | ||
|
|
d33b47d15a | ||
|
|
e4a0a08d13 | ||
|
|
24a69166f0 |
10
.github/workflows/build_and_test.yml
vendored
10
.github/workflows/build_and_test.yml
vendored
@@ -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:
|
||||
|
||||
57
README.MD
57
README.MD
@@ -39,16 +39,40 @@ Various compression implementations that are used across multiple projects. Most
|
||||
| [DotNetZip](https://github.com/DinoChiesa/DotNetZip) | BZip2 and DEFLATE implementations; minor edits have been made |
|
||||
| [ZLibPort](https://github.com/Nanook/zlib-C-To-CSharp-Port) | Adds zlib code for internal and external use; minor edits have been made |
|
||||
|
||||
### `SabreTools.IO.Encryption`
|
||||
|
||||
Various encryption implementations that are used across multiple projects. Most of the implementations are be ports of existing C and C++ code.
|
||||
|
||||
#### Supported Encryption Schemes
|
||||
|
||||
| Encryption Scheme | Encrypt | Decrypt | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| AES/CTR | Yes | Yes | Subset of functionality exposed from [The Bouncy Castle Cryptography Library For .NET](https://github.com/bcgit/bc-csharp) |
|
||||
| MoPaQ | No | Yes | Used to encrypt and decrypt MoPaQ tables for processing |
|
||||
|
||||
### `SabreTools.IO.Extensions`
|
||||
|
||||
Extensions for `BinaryReader`, `byte[]`, and `Stream` to help with reading and writing various data types. Some data types are locked behind .NET version support.
|
||||
|
||||
This namespace also contains other various extensions that help with common functionality and safe access.
|
||||
|
||||
### `SabreTools.IO.Interfaces`
|
||||
|
||||
Common interfaces used mainly internal to the library.
|
||||
|
||||
| Interface | Notes |
|
||||
| --- | --- |
|
||||
| `IMatch<T>` | Represents a matcher for a generic type |
|
||||
| `IMatchSet<T, U>` | Represents a set of `IMatch<T>` types |
|
||||
|
||||
### `SabreTools.IO.Logging`
|
||||
|
||||
Logic for a logging system, including writing to console and textfile outputs. There are 4 possible log levels for logging statements to be invoked with. There is also a stopwatch implementation included for logging statements with automatic timespan tracking.
|
||||
|
||||
### `SabreTools.IO.Matching`
|
||||
|
||||
Classes designed to make matching contents and paths easier. These classes allow for both grouped and single matching as well as post-processing of matched information.
|
||||
|
||||
### `SabreTools.IO.Readers` and `SabreTools.IO.Writers`
|
||||
|
||||
Reading and writing support for the following file types:
|
||||
@@ -63,8 +87,41 @@ For a generic INI implementation, see `SabreTools.IO.IniFile`.
|
||||
|
||||
Custom `Stream` implementations that are required for specialized use:
|
||||
|
||||
- `BufferedStream`: A format that is not a true stream implementation used for buffered, single-byte reads
|
||||
- `ReadOnlyBitStream`: A readonly stream implementation allowing bitwise reading
|
||||
- `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".
|
||||
|
||||
## Releases
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.IO.Compare;
|
||||
using SabreTools.Text.Compare;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.IO.Test.Compare
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using SabreTools.IO.Compare;
|
||||
using SabreTools.Text.Compare;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.IO.Test.Compare
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.IO.Compare;
|
||||
using SabreTools.Text.Compare;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.IO.Test.Compare
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
{
|
||||
|
||||
@@ -424,6 +424,86 @@ namespace SabreTools.IO.Test.Extensions
|
||||
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[0], 0, new byte[0])]
|
||||
[InlineData(new byte[0], 1234, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2 }, 0, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2 }, 1234, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xA4 })]
|
||||
public void Add_NumericInput(byte[] self, uint add, byte[] expected)
|
||||
{
|
||||
byte[] actual = self.Add(add);
|
||||
|
||||
Assert.Equal(expected.Length, actual.Length);
|
||||
if (actual.Length > 0)
|
||||
Assert.True(actual.EqualsExactly(expected));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[0], new byte[0], new byte[0])]
|
||||
[InlineData(new byte[0], new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[0], new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0x00, 0x00 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x00, 0x00 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0x09, 0xA4 })]
|
||||
[InlineData(new byte[] { 0xAB, 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0xAB, 0x09, 0xA4 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0xAB, 0x04, 0xD2 }, new byte[] { 0xAB, 0x09, 0xA4 })]
|
||||
public void Add_ArrayInput(byte[] self, byte[] add, byte[] expected)
|
||||
{
|
||||
byte[] actual = self.Add(add);
|
||||
|
||||
Assert.Equal(expected.Length, actual.Length);
|
||||
if (actual.Length > 0)
|
||||
Assert.True(actual.EqualsExactly(expected));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RotateLeft
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[0], 0, new byte[0])]
|
||||
[InlineData(new byte[] { 0x01 }, 0, new byte[] { 0x01 })]
|
||||
[InlineData(new byte[] { 0x01 }, 1, new byte[] { 0x02 })]
|
||||
[InlineData(new byte[] { 0x80 }, 1, new byte[] { 0x01 })]
|
||||
[InlineData(new byte[] { 0x00, 0x01 }, 0, new byte[] { 0x00, 0x01 })]
|
||||
[InlineData(new byte[] { 0x00, 0x01 }, 1, new byte[] { 0x00, 0x02 })]
|
||||
[InlineData(new byte[] { 0x00, 0x80 }, 1, new byte[] { 0x01, 0x00 })]
|
||||
[InlineData(new byte[] { 0x80, 0x00 }, 1, new byte[] { 0x00, 0x01 })]
|
||||
public void RotateLeftTest(byte[] self, int numBits, byte[] expected)
|
||||
{
|
||||
byte[] actual = self.RotateLeft(numBits);
|
||||
|
||||
Assert.Equal(expected.Length, actual.Length);
|
||||
if (actual.Length > 0)
|
||||
Assert.True(actual.EqualsExactly(expected));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Xor
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[0], new byte[0], new byte[0])]
|
||||
[InlineData(new byte[0], new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[0], new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0x00, 0x00 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x00, 0x00 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0x00, 0x00 })]
|
||||
[InlineData(new byte[] { 0xAB, 0x04, 0xD2 }, new byte[] { 0x04, 0xD2 }, new byte[] { 0xAB, 0x00, 0x00 })]
|
||||
[InlineData(new byte[] { 0x04, 0xD2 }, new byte[] { 0xAB, 0x04, 0xD2 }, new byte[] { 0xAB, 0x00, 0x00 })]
|
||||
public void XorTest(byte[] self, byte[] add, byte[] expected)
|
||||
{
|
||||
byte[] actual = self.Xor(add);
|
||||
|
||||
Assert.Equal(expected.Length, actual.Length);
|
||||
if (actual.Length > 0)
|
||||
Assert.True(actual.EqualsExactly(expected));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToHexString
|
||||
|
||||
[Fact]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
@@ -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()
|
||||
{
|
||||
|
||||
249
SabreTools.IO.Test/Numerics/BothInt16Tests.cs
Normal file
249
SabreTools.IO.Test/Numerics/BothInt16Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
249
SabreTools.IO.Test/Numerics/BothInt32Tests.cs
Normal file
249
SabreTools.IO.Test/Numerics/BothInt32Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
249
SabreTools.IO.Test/Numerics/BothInt64Tests.cs
Normal file
249
SabreTools.IO.Test/Numerics/BothInt64Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
249
SabreTools.IO.Test/Numerics/BothInt8Tests.cs
Normal file
249
SabreTools.IO.Test/Numerics/BothInt8Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
238
SabreTools.IO.Test/Numerics/BothUInt16Tests.cs
Normal file
238
SabreTools.IO.Test/Numerics/BothUInt16Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
238
SabreTools.IO.Test/Numerics/BothUInt32Tests.cs
Normal file
238
SabreTools.IO.Test/Numerics/BothUInt32Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
238
SabreTools.IO.Test/Numerics/BothUInt64Tests.cs
Normal file
238
SabreTools.IO.Test/Numerics/BothUInt64Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
238
SabreTools.IO.Test/Numerics/BothUInt8Tests.cs
Normal file
238
SabreTools.IO.Test/Numerics/BothUInt8Tests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
124
SabreTools.IO.Test/Transform/CombineTests.cs
Normal file
124
SabreTools.IO.Test/Transform/CombineTests.cs
Normal 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
|
||||
}
|
||||
}
|
||||
124
SabreTools.IO.Test/Transform/SplitTests.cs
Normal file
124
SabreTools.IO.Test/Transform/SplitTests.cs
Normal 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
|
||||
}
|
||||
}
|
||||
76
SabreTools.IO.Test/Transform/SwapTests.cs
Normal file
76
SabreTools.IO.Test/Transform/SwapTests.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SabreTools.IO.Compare
|
||||
namespace SabreTools.Text.Compare
|
||||
{
|
||||
public class NaturalComparer : Comparer<string>, IDisposable
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace SabreTools.IO.Compare
|
||||
namespace SabreTools.Text.Compare
|
||||
{
|
||||
internal static class NaturalComparerUtil
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SabreTools.IO.Compare
|
||||
namespace SabreTools.Text.Compare
|
||||
{
|
||||
public class NaturalReversedComparer : Comparer<string>, IDisposable
|
||||
{
|
||||
|
||||
125
SabreTools.IO/Encryption/AESCTR.cs
Normal file
125
SabreTools.IO/Encryption/AESCTR.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace SabreTools.IO.Encryption
|
||||
{
|
||||
public static class AESCTR
|
||||
{
|
||||
/// <summary>
|
||||
/// Create AES decryption cipher and intialize
|
||||
/// </summary>
|
||||
/// <param name="key">Byte array representation of 128-bit encryption key</param>
|
||||
/// <param name="iv">AES initial value for counter</param>
|
||||
/// <returns>Initialized AES cipher</returns>
|
||||
public static IBufferedCipher CreateDecryptionCipher(byte[] key, byte[] iv)
|
||||
{
|
||||
if (key.Length != 16)
|
||||
throw new ArgumentOutOfRangeException(nameof(key));
|
||||
|
||||
var keyParam = new KeyParameter(key);
|
||||
var cipher = CipherUtilities.GetCipher("AES/CTR");
|
||||
cipher.Init(forEncryption: false, new ParametersWithIV(keyParam, iv));
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create AES encryption cipher and intialize
|
||||
/// </summary>
|
||||
/// <param name="key">Byte array representation of 128-bit encryption key</param>
|
||||
/// <param name="iv">AES initial value for counter</param>
|
||||
/// <returns>Initialized AES cipher</returns>
|
||||
public static IBufferedCipher CreateEncryptionCipher(byte[] key, byte[] iv)
|
||||
{
|
||||
if (key.Length != 16)
|
||||
throw new ArgumentOutOfRangeException(nameof(key));
|
||||
|
||||
var keyParam = new KeyParameter(key);
|
||||
var cipher = CipherUtilities.GetCipher("AES/CTR");
|
||||
cipher.Init(forEncryption: true, new ParametersWithIV(keyParam, iv));
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an AES operation using an existing cipher
|
||||
/// </summary>
|
||||
public static void PerformOperation(uint size,
|
||||
IBufferedCipher cipher,
|
||||
Stream input,
|
||||
Stream output,
|
||||
Action<string>? progress = null)
|
||||
{
|
||||
// Get MiB-aligned block count and extra byte count
|
||||
int blockCount = (int)((long)size / (1024 * 1024));
|
||||
int extraBytes = (int)((long)size % (1024 * 1024));
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (blockCount > 0)
|
||||
{
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(1024 * 1024);
|
||||
byte[] processedBytes = cipher.ProcessBytes(readBytes);
|
||||
output.Write(processedBytes);
|
||||
output.Flush();
|
||||
progress?.Invoke($"{i} / {blockCount + 1} MB");
|
||||
}
|
||||
}
|
||||
|
||||
// Process additional data
|
||||
if (extraBytes > 0)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(extraBytes);
|
||||
byte[] finalBytes = cipher.DoFinal(readBytes);
|
||||
output.Write(finalBytes);
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
progress?.Invoke($"{blockCount + 1} / {blockCount + 1} MB... Done!\r\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an AES operation using two existing ciphers
|
||||
/// </summary>
|
||||
public static void PerformOperation(uint size,
|
||||
IBufferedCipher firstCipher,
|
||||
IBufferedCipher secondCipher,
|
||||
Stream input,
|
||||
Stream output,
|
||||
Action<string>? progress = null)
|
||||
{
|
||||
// Get MiB-aligned block count and extra byte count
|
||||
int blockCount = (int)((long)size / (1024 * 1024));
|
||||
int extraBytes = (int)((long)size % (1024 * 1024));
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (blockCount > 0)
|
||||
{
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(1024 * 1024);
|
||||
byte[] firstProcessedBytes = firstCipher.ProcessBytes(readBytes);
|
||||
byte[] secondProcessedBytes = secondCipher.ProcessBytes(firstProcessedBytes);
|
||||
output.Write(secondProcessedBytes);
|
||||
output.Flush();
|
||||
progress?.Invoke($"{i} / {blockCount + 1} MB");
|
||||
}
|
||||
}
|
||||
|
||||
// Process additional data
|
||||
if (extraBytes > 0)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(extraBytes);
|
||||
byte[] firstFinalBytes = firstCipher.DoFinal(readBytes);
|
||||
byte[] secondFinalBytes = secondCipher.DoFinal(firstFinalBytes);
|
||||
output.Write(secondFinalBytes);
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
progress?.Invoke($"{blockCount + 1} / {blockCount + 1} MB... Done!\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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))
|
||||
|
||||
@@ -237,6 +237,176 @@ namespace SabreTools.IO.Extensions
|
||||
|
||||
#endregion
|
||||
|
||||
#region Math
|
||||
|
||||
/// <summary>
|
||||
/// Add an integer value to a number represented by a byte array
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to add to</param>
|
||||
/// <param name="add">Amount to add</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Add(this byte[] self, uint add)
|
||||
{
|
||||
// If nothing is being added, just return
|
||||
if (add == 0)
|
||||
return self;
|
||||
|
||||
// Get the big-endian representation of the value
|
||||
byte[] addBytes = BitConverter.GetBytes(add);
|
||||
Array.Reverse(addBytes);
|
||||
|
||||
// Pad the array out to 16 bytes
|
||||
byte[] paddedBytes = new byte[16];
|
||||
Array.Copy(addBytes, 0, paddedBytes, 12, 4);
|
||||
|
||||
// If the input is empty, just return the added value
|
||||
if (self.Length == 0)
|
||||
return paddedBytes;
|
||||
|
||||
return self.Add(paddedBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two numbers represented by byte arrays
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to add to</param>
|
||||
/// <param name="add">Amount to add</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Add(this byte[] self, byte[] add)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0 && add.Length == 0)
|
||||
return [];
|
||||
else if (self.Length > 0 && add.Length == 0)
|
||||
return self;
|
||||
else if (self.Length == 0 && add.Length > 0)
|
||||
return add;
|
||||
|
||||
// Setup the output array
|
||||
int outLength = Math.Max(self.Length, add.Length);
|
||||
byte[] output = new byte[outLength];
|
||||
|
||||
// Loop adding with carry
|
||||
uint carry = 0;
|
||||
for (int i = 0; i < outLength; i++)
|
||||
{
|
||||
int selfIndex = self.Length - i - 1;
|
||||
uint selfValue = selfIndex >= 0 ? self[selfIndex] : 0u;
|
||||
|
||||
int addIndex = add.Length - i - 1;
|
||||
uint addValue = addIndex >= 0 ? add[addIndex] : 0u;
|
||||
|
||||
uint next = selfValue + addValue + carry;
|
||||
carry = next >> 8;
|
||||
|
||||
int outputIndex = output.Length - i - 1;
|
||||
output[outputIndex] = (byte)(next & 0xFF);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a rotate left on a byte array
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array value to rotate</param>
|
||||
/// <param name="numBits">Number of bits to rotate</param>
|
||||
/// <returns>Rotated byte array value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] RotateLeft(this byte[] self, int numBits)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0)
|
||||
return [];
|
||||
else if (numBits == 0)
|
||||
return self;
|
||||
|
||||
byte[] output = new byte[self.Length];
|
||||
Array.Copy(self, output, output.Length);
|
||||
|
||||
// Shift by bytes
|
||||
while (numBits >= 8)
|
||||
{
|
||||
byte temp = output[0];
|
||||
for (int i = 0; i < output.Length - 1; i++)
|
||||
{
|
||||
output[i] = output[i + 1];
|
||||
}
|
||||
|
||||
output[output.Length - 1] = temp;
|
||||
numBits -= 8;
|
||||
}
|
||||
|
||||
// Shift by bits
|
||||
if (numBits > 0)
|
||||
{
|
||||
byte bitMask = (byte)(8 - numBits), carry, wrap = 0;
|
||||
for (int i = 0; i < output.Length; i++)
|
||||
{
|
||||
carry = (byte)((255 << bitMask & output[i]) >> bitMask);
|
||||
|
||||
// Make sure the first byte carries to the end
|
||||
if (i == 0)
|
||||
wrap = carry;
|
||||
|
||||
// Otherwise, move to the last byte
|
||||
else
|
||||
output[i - 1] |= carry;
|
||||
|
||||
// Shift the current bits
|
||||
output[i] <<= numBits;
|
||||
}
|
||||
|
||||
// Make sure the wrap happens
|
||||
output[output.Length - 1] |= wrap;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XOR two numbers represented by byte arrays
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to XOR to</param>
|
||||
/// <param name="xor">Amount to XOR</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Xor(this byte[] self, byte[] xor)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0 && xor.Length == 0)
|
||||
return [];
|
||||
else if (self.Length > 0 && xor.Length == 0)
|
||||
return self;
|
||||
else if (self.Length == 0 && xor.Length > 0)
|
||||
return xor;
|
||||
|
||||
// Setup the output array
|
||||
int outLength = Math.Max(self.Length, xor.Length);
|
||||
byte[] output = new byte[outLength];
|
||||
|
||||
// Loop XOR
|
||||
for (int i = 0; i < outLength; i++)
|
||||
{
|
||||
int selfIndex = self.Length - i - 1;
|
||||
uint selfValue = selfIndex >= 0 ? self[selfIndex] : 0u;
|
||||
|
||||
int xorIndex = xor.Length - i - 1;
|
||||
uint xorValue = xorIndex >= 0 ? xor[xorIndex] : 0u;
|
||||
|
||||
uint next = selfValue ^ xorValue;
|
||||
|
||||
int outputIndex = output.Length - i - 1;
|
||||
output[outputIndex] = (byte)(next & 0xFF);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Strings
|
||||
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
234
SabreTools.IO/Numerics/BothEndian.cs
Normal file
234
SabreTools.IO/Numerics/BothEndian.cs
Normal 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
|
||||
}
|
||||
}
|
||||
143
SabreTools.IO/Numerics/BothInt16.cs
Normal file
143
SabreTools.IO/Numerics/BothInt16.cs
Normal 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
|
||||
}
|
||||
}
|
||||
143
SabreTools.IO/Numerics/BothInt32.cs
Normal file
143
SabreTools.IO/Numerics/BothInt32.cs
Normal 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
|
||||
}
|
||||
}
|
||||
143
SabreTools.IO/Numerics/BothInt64.cs
Normal file
143
SabreTools.IO/Numerics/BothInt64.cs
Normal 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
|
||||
}
|
||||
}
|
||||
143
SabreTools.IO/Numerics/BothInt8.cs
Normal file
143
SabreTools.IO/Numerics/BothInt8.cs
Normal 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
|
||||
}
|
||||
}
|
||||
129
SabreTools.IO/Numerics/BothUInt16.cs
Normal file
129
SabreTools.IO/Numerics/BothUInt16.cs
Normal 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
|
||||
}
|
||||
}
|
||||
129
SabreTools.IO/Numerics/BothUInt32.cs
Normal file
129
SabreTools.IO/Numerics/BothUInt32.cs
Normal 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
|
||||
}
|
||||
}
|
||||
129
SabreTools.IO/Numerics/BothUInt64.cs
Normal file
129
SabreTools.IO/Numerics/BothUInt64.cs
Normal 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
|
||||
}
|
||||
}
|
||||
129
SabreTools.IO/Numerics/BothUInt8.cs
Normal file
129
SabreTools.IO/Numerics/BothUInt8.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.IO.Compare;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Text.Compare;
|
||||
|
||||
namespace SabreTools.IO
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.7.5</Version>
|
||||
<Version>1.8.0</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
@@ -34,7 +34,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.5.0" />
|
||||
<PackageReference Include="BouncyCastle.NetCore" Version="1.9.0" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
158
SabreTools.IO/Transform/Combine.cs
Normal file
158
SabreTools.IO/Transform/Combine.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
SabreTools.IO/Transform/Enums.cs
Normal file
54
SabreTools.IO/Transform/Enums.cs
Normal 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,
|
||||
}
|
||||
}
|
||||
177
SabreTools.IO/Transform/Split.cs
Normal file
177
SabreTools.IO/Transform/Split.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
SabreTools.IO/Transform/Swap.cs
Normal file
162
SabreTools.IO/Transform/Swap.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user