mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-01-11 19:44:55 +00:00
feat[BigEndianBitConverter]: Added BigEndianBitConverter
This commit is contained in:
154
ICD.Common.Utils.Tests/BigEndianBitConverterTest.cs
Normal file
154
ICD.Common.Utils.Tests/BigEndianBitConverterTest.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace ICD.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BigEndianBitConverterTest
|
||||
{
|
||||
[TestCase(ushort.MaxValue, new byte[] {0xFF, 0xFF}, 0)]
|
||||
[TestCase(ushort.MinValue, new byte[] {0x00, 0x00}, 0)]
|
||||
[TestCase((ushort)255, new byte[]{0x00, 0xFF}, 0)]
|
||||
[TestCase((ushort)65280, new byte[]{0xFF, 0x00},0)]
|
||||
[TestCase(ushort.MaxValue, new byte[] {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00}, 2)]
|
||||
[TestCase(ushort.MinValue, new byte[] { 0xFF, 0x00, 0x00, 0xFF, 0xFF}, 1)]
|
||||
[TestCase((ushort)255, new byte[]{0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00}, 3)]
|
||||
[TestCase((ushort)65280, new byte[]{0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF},4)]
|
||||
[TestCase((ushort)240, new byte[]{0x00, 0xFF,0x00, 0xF0, 0xFF}, 2)]
|
||||
[TestCase((ushort)15, new byte[]{0x00, 0x0F},0)]
|
||||
public void ToUshortTest(ushort expectedResult, byte[] value, int startIndex)
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
|
||||
Assert.AreEqual(expectedResult, BigEndianBitConverter.ToUshort(value, startIndex));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToUshortExceptionTest()
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
byte[] values = { 0x00, 0xFF, 0x0F, 0xF0, 0xFF, 0xAA, 0x55, 0xF1, 0x1F };
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => BigEndianBitConverter.ToUshort(null, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToUshort(values, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToUshort(values, 9));
|
||||
Assert.Throws<ArgumentException>(() => BigEndianBitConverter.ToUshort(values, 8));
|
||||
}
|
||||
|
||||
[TestCase(short.MaxValue, new byte[] {0x7F, 0xFF}, 0)]
|
||||
[TestCase(short.MinValue, new byte[] {0x80, 0x00}, 0)]
|
||||
[TestCase(0, new byte[] {0x00, 0x00},0)]
|
||||
[TestCase(-1, new byte[] {0xFF, 0xFF}, 0)]
|
||||
[TestCase((short)255, new byte[]{0x00, 0xFF}, 0)]
|
||||
[TestCase((short)-256, new byte[]{0xFF, 0x00},0)]
|
||||
[TestCase(short.MaxValue, new byte[] {0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00}, 2)]
|
||||
[TestCase(short.MinValue, new byte[] { 0xFF, 0x80, 0x00, 0xFF, 0xFF}, 1)]
|
||||
[TestCase((short)255, new byte[]{0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00}, 3)]
|
||||
[TestCase((short)-256, new byte[]{0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF},4)]
|
||||
[TestCase((short)240, new byte[]{0x00, 0xFF,0x00, 0xF0, 0xFF}, 2)]
|
||||
[TestCase((short)15, new byte[]{0x00, 0x0F},0)]
|
||||
public void ToShortTest(short expectedResult, byte[] value, int startIndex)
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
|
||||
Assert.AreEqual(expectedResult, BigEndianBitConverter.ToShort(value, startIndex));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToShortExceptionTest()
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
byte[] values = { 0x00, 0xFF, 0x0F, 0xF0, 0xFF, 0xAA, 0x55, 0xF1, 0x1F };
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => BigEndianBitConverter.ToShort(null, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToShort(values, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToShort(values, 9));
|
||||
Assert.Throws<ArgumentException>(() => BigEndianBitConverter.ToShort(values, 8));
|
||||
}
|
||||
|
||||
[TestCase(uint.MaxValue, new byte[] {0xFF, 0xFF, 0xFF, 0xFF}, 0)]
|
||||
[TestCase(uint.MinValue, new byte[] {0x00, 0x00, 0x00, 0x00}, 0)]
|
||||
[TestCase((uint)255, new byte[]{ 0x00, 0x00, 0x00, 0xFF}, 0)]
|
||||
[TestCase((uint)4278190080, new byte[]{0xFF, 0x00, 0x00, 0x00},0)]
|
||||
[TestCase(uint.MaxValue, new byte[] {0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 2)]
|
||||
[TestCase(uint.MinValue, new byte[] { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}, 1)]
|
||||
[TestCase((uint)255, new byte[]{0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, 3)]
|
||||
[TestCase((uint)4278190080, new byte[]{0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF},4)]
|
||||
[TestCase((uint)15728895, new byte[]{0x00, 0xFF,0x00, 0xF0, 0x00, 0xFF, 0xFF}, 2)]
|
||||
[TestCase((uint)1044735, new byte[]{0x00, 0x0F, 0xF0, 0xFF},0)]
|
||||
public void ToUintTest(uint expectedResult, byte[] value, int startIndex)
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
|
||||
Assert.AreEqual(expectedResult, BigEndianBitConverter.ToUint(value, startIndex));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToUintExceptionTest()
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
byte[] values = { 0x00, 0xFF, 0x0F, 0xF0, 0xFF, 0xAA, 0x55, 0xF1, 0x1F };
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => BigEndianBitConverter.ToUint(null, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToUint(values, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToUint(values, 9));
|
||||
Assert.Throws<ArgumentException>(() => BigEndianBitConverter.ToUint(values, 6));
|
||||
}
|
||||
|
||||
[TestCase(int.MaxValue, new byte[] {0x7F, 0xFF, 0xFF, 0xFF}, 0)]
|
||||
[TestCase(int.MinValue, new byte[] {0x80, 0x00, 0x00, 0x00}, 0)]
|
||||
[TestCase(0, new byte[] {0x00, 0x00, 0x00, 0x00}, 0)]
|
||||
[TestCase(255, new byte[]{ 0x00, 0x00, 0x00, 0xFF}, 0)]
|
||||
[TestCase(-1, new byte[]{0xFF, 0xFF, 0xFF, 0xFF},0)]
|
||||
[TestCase(-16777216, new byte[]{0xFF, 0x00, 0x00, 0x00},0)]
|
||||
[TestCase(int.MaxValue, new byte[] {0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 2)]
|
||||
[TestCase(int.MinValue, new byte[] { 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF}, 1)]
|
||||
[TestCase(255, new byte[]{0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, 3)]
|
||||
[TestCase(-16777216, new byte[]{0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF},4)]
|
||||
[TestCase(15728895, new byte[]{0x00, 0xFF,0x00, 0xF0, 0x00, 0xFF, 0xFF}, 2)]
|
||||
[TestCase(1044735, new byte[]{0x00, 0x0F, 0xF0, 0xFF},0)]
|
||||
public void ToIntTest(int expectedResult, byte[] value, int startIndex)
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
|
||||
Assert.AreEqual(expectedResult, BigEndianBitConverter.ToInt(value, startIndex));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToIntExceptionTest()
|
||||
{
|
||||
// We use system BitConverter for systems that are already big-endian
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Assert.Inconclusive();
|
||||
|
||||
byte[] values = { 0x00, 0xFF, 0x0F, 0xF0, 0xFF, 0xAA, 0x55, 0xF1, 0x1F };
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => BigEndianBitConverter.ToInt(null, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToInt(values, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => BigEndianBitConverter.ToInt(values, 9));
|
||||
Assert.Throws<ArgumentException>(() => BigEndianBitConverter.ToInt(values, 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
183
ICD.Common.Utils/BigEndianBitConverter.cs
Normal file
183
ICD.Common.Utils/BigEndianBitConverter.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static class BigEndianBitConverter
|
||||
{
|
||||
private const byte FULL_BYTE = 0xFF;
|
||||
|
||||
public static ushort ToUshort([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
return unchecked((ushort)ToShort(value, startIndex));
|
||||
}
|
||||
|
||||
public static short ToShort([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.ToInt16(value, startIndex);
|
||||
|
||||
const int bytes = sizeof(short);
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (startIndex < 0 || startIndex >= value.Length)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (startIndex > value.Length - bytes)
|
||||
throw new ArgumentException("Array plus start index too small");
|
||||
|
||||
short result = 0;
|
||||
for (int i = 0; i < bytes; i++)
|
||||
result |= (short)(value[i + startIndex] << GetBitShift(i, bytes));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static uint ToUint([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
return unchecked((uint)ToInt(value, startIndex));
|
||||
}
|
||||
|
||||
public static int ToInt([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.ToInt32(value, startIndex);
|
||||
|
||||
const int bytes = sizeof(int);
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (startIndex < 0 || startIndex >= value.Length)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (startIndex > value.Length - bytes)
|
||||
throw new ArgumentException("Array plus start index too small");
|
||||
|
||||
int result = 0;
|
||||
for (int i = 0; i < bytes; i++)
|
||||
result |= value[i + startIndex] << GetBitShift(i, bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ulong ToUlong([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
return unchecked((ulong)ToLong(value, startIndex));
|
||||
}
|
||||
|
||||
public static long ToLong([NotNull] byte[] value, int startIndex)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.ToInt64(value, startIndex);
|
||||
|
||||
const int bytes = sizeof(long);
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (startIndex < 0 || startIndex >= value.Length)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (startIndex > value.Length - bytes)
|
||||
throw new ArgumentException("Array plus start index too small");
|
||||
|
||||
int result = 0;
|
||||
for (int i = 0; i < bytes; i++)
|
||||
result |= value[i + startIndex] << GetBitShift(i, bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(int value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(int);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
public static byte[] GetBytes(uint value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(uint);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(short value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(short);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(ushort value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(short);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(long value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(long);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(ulong value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
return BitConverter.GetBytes(value);
|
||||
|
||||
const int total_bytes = sizeof(ulong);
|
||||
|
||||
byte[] response = new byte[total_bytes];
|
||||
|
||||
for (int i = 0; i < total_bytes; i++)
|
||||
response[i] = (byte)(value >> GetBitShift(i,total_bytes) & FULL_BYTE);
|
||||
|
||||
return response;
|
||||
}
|
||||
private static int GetBitShift(int byteNumber, int totalBytes)
|
||||
{
|
||||
return ((totalBytes - 1 - byteNumber) * 8);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,7 @@
|
||||
<Compile Include="Attributes\AbstractIcdAttribute.cs" />
|
||||
<Compile Include="Attributes\IIcdAttribute.cs" />
|
||||
<Compile Include="Attributes\RangeAttribute.cs" />
|
||||
<Compile Include="BigEndianBitConverter.cs" />
|
||||
<Compile Include="Collections\BiDictionary.cs" />
|
||||
<Compile Include="Collections\IcdOrderedDictionary.cs" />
|
||||
<Compile Include="Collections\IcdSortedDictionary.cs" />
|
||||
|
||||
Reference in New Issue
Block a user