Move to file scoped namespaces.

This commit is contained in:
2022-03-06 13:29:37 +00:00
parent 31750d5978
commit cb79ff60d6
13 changed files with 1461 additions and 1474 deletions

View File

@@ -27,55 +27,54 @@
using System;
using System.Text;
namespace Aaru.Helpers
namespace Aaru.Helpers;
public static partial class ArrayHelpers
{
public static partial class ArrayHelpers
/// <summary>Fills an array with the specified value</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T value) => ArrayFill(destinationArray, new[]
{
/// <summary>Fills an array with the specified value</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T value) => ArrayFill(destinationArray, new[]
{
value
});
value
});
/// <summary>Fills an array with the contents of the specified array</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T[] value)
{
if(destinationArray == null)
throw new ArgumentNullException(nameof(destinationArray));
/// <summary>Fills an array with the contents of the specified array</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T[] value)
{
if(destinationArray == null)
throw new ArgumentNullException(nameof(destinationArray));
if(value.Length > destinationArray.Length)
throw new ArgumentException("Length of value array must not be more than length of destination");
if(value.Length > destinationArray.Length)
throw new ArgumentException("Length of value array must not be more than length of destination");
// set the initial array value
Array.Copy(value, destinationArray, value.Length);
// set the initial array value
Array.Copy(value, destinationArray, value.Length);
int arrayToFillHalfLength = destinationArray.Length / 2;
int copyLength;
int arrayToFillHalfLength = destinationArray.Length / 2;
int copyLength;
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}
/// <summary>Converts a byte array to its hexadecimal representation</summary>
/// <param name="array">Byte array</param>
/// <param name="upper"><c>true</c> to use uppercase</param>
/// <returns></returns>
public static string ByteArrayToHex(byte[] array, bool upper = false)
{
var sb = new StringBuilder();
/// <summary>Converts a byte array to its hexadecimal representation</summary>
/// <param name="array">Byte array</param>
/// <param name="upper"><c>true</c> to use uppercase</param>
/// <returns></returns>
public static string ByteArrayToHex(byte[] array, bool upper = false)
{
var sb = new StringBuilder();
for(long i = 0; i < array.LongLength; i++)
sb.AppendFormat("{0:x2}", array[i]);
for(long i = 0; i < array.LongLength; i++)
sb.AppendFormat("{0:x2}", array[i]);
return upper ? sb.ToString().ToUpper() : sb.ToString();
}
return upper ? sb.ToString().ToUpper() : sb.ToString();
}
}

View File

@@ -32,19 +32,18 @@
using System.Linq;
namespace Aaru.Helpers
{
/// <summary>Helper operations to work with arrays</summary>
public static partial class ArrayHelpers
{
/// <summary>Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)</summary>
/// <param name="array">Array</param>
/// <returns>True if null or whitespace</returns>
public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b == 0x00 || b == 0x20) != false;
namespace Aaru.Helpers;
/// <summary>Checks if an array is null or filled with the NULL byte (0x00)</summary>
/// <param name="array">Array</param>
/// <returns>True if null</returns>
public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false;
}
/// <summary>Helper operations to work with arrays</summary>
public static partial class ArrayHelpers
{
/// <summary>Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)</summary>
/// <param name="array">Array</param>
/// <returns>True if null or whitespace</returns>
public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b == 0x00 || b == 0x20) != false;
/// <summary>Checks if an array is null or filled with the NULL byte (0x00)</summary>
/// <param name="array">Array</param>
/// <returns>True if null</returns>
public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false;
}

View File

@@ -33,292 +33,291 @@
using System;
using System.Linq;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
/// </summary>
public static class BigEndianBitConverter
{
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
/// <exception cref="NotImplementedException">It is not currently implemented</exception>
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
/// <summary>Returns the specified Boolean value as an array of bytes.</summary>
/// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns>
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
/// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
/// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
/// array.
/// </summary>
public static class BigEndianBitConverter
{
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
/// <exception cref="NotImplementedException">It is not currently implemented</exception>
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns the specified Boolean value as an array of bytes.</summary>
/// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns>
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static short ToInt16(byte[] value, int startIndex) =>
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
/// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
/// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static int ToInt32(byte[] value, int startIndex) =>
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
/// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static long ToInt64(byte[] value, int startIndex) =>
BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
/// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>
/// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
/// array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A single-precision floating point number formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static float ToSingle(byte[] value, int startIndex) =>
BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
/// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>
/// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
/// representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
/// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static string ToString(byte[] value, int startIndex) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex);
/// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <param name="length">The number of array elements in value to convert.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex or length is less than zero. -or- startIndex is greater
/// than zero and is greater than or equal to the length of value.
/// </exception>
/// <exception cref="System.ArgumentException">
/// The combination of startIndex and length does not specify a position within
/// value; that is, the startIndex parameter is greater than the length of value minus the length parameter.
/// </exception>
public static string ToString(byte[] value, int startIndex, int length) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
/// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">The array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">startIndex equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ushort ToUInt16(byte[] value, int startIndex) =>
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
/// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 3, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static uint ToUInt32(byte[] value, int startIndex) =>
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
/// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 7, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ulong ToUInt64(byte[] value, int startIndex) =>
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
/// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>
/// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
/// array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static short ToInt16(byte[] value, int startIndex) =>
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
/// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static int ToInt32(byte[] value, int startIndex) =>
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
/// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static long ToInt64(byte[] value, int startIndex) =>
BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
/// <summary>
/// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
/// array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A single-precision floating point number formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static float ToSingle(byte[] value, int startIndex) =>
BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
/// <summary>
/// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
/// representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static string ToString(byte[] value, int startIndex) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex);
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <param name="length">The number of array elements in value to convert.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex or length is less than zero. -or- startIndex is greater
/// than zero and is greater than or equal to the length of value.
/// </exception>
/// <exception cref="System.ArgumentException">
/// The combination of startIndex and length does not specify a position within
/// value; that is, the startIndex parameter is greater than the length of value minus the length parameter.
/// </exception>
public static string ToString(byte[] value, int startIndex, int length) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
/// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">The array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">startIndex equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ushort ToUInt16(byte[] value, int startIndex) =>
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
/// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 3, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static uint ToUInt32(byte[] value, int startIndex) =>
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
/// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 7, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ulong ToUInt64(byte[] value, int startIndex) =>
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
/// <summary>Converts a big endian byte array representation of a GUID into the .NET Guid structure</summary>
/// <param name="value">Byte array containing a GUID in big endian</param>
/// <param name="startIndex">Start of the byte array to process</param>
/// <returns>Processed Guid</returns>
public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
ToUInt16(value, 4 + startIndex),
ToUInt16(value, 6 + startIndex),
value[8 + startIndex + 0],
value[8 + startIndex + 1],
value[8 + startIndex + 2],
value[8 + startIndex + 3],
value[8 + startIndex + 5],
value[8 + startIndex + 5],
value[8 + startIndex + 6],
value[8 + startIndex + 7]);
}
/// <summary>Converts a big endian byte array representation of a GUID into the .NET Guid structure</summary>
/// <param name="value">Byte array containing a GUID in big endian</param>
/// <param name="startIndex">Start of the byte array to process</param>
/// <returns>Processed Guid</returns>
public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
ToUInt16(value, 4 + startIndex),
ToUInt16(value, 6 + startIndex),
value[8 + startIndex + 0],
value[8 + startIndex + 1],
value[8 + startIndex + 2],
value[8 + startIndex + 3],
value[8 + startIndex + 5],
value[8 + startIndex + 5],
value[8 + startIndex + 6],
value[8 + startIndex + 7]);
}

View File

@@ -36,16 +36,15 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Describes the endianness of bits on a data structure</summary>
public enum BitEndian
{
/// <summary>Describes the endianness of bits on a data structure</summary>
public enum BitEndian
{
/// <summary>Little-endian, or least significant bit</summary>
Little,
/// <summary>Big-endian, or most significant bit</summary>
Big,
/// <summary>PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them</summary>
Pdp
}
/// <summary>Little-endian, or least significant bit</summary>
Little,
/// <summary>Big-endian, or most significant bit</summary>
Big,
/// <summary>PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them</summary>
Pdp
}

29
CHS.cs
View File

@@ -30,20 +30,19 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Helper operations to work with CHS values</summary>
public static class CHS
{
/// <summary>Helper operations to work with CHS values</summary>
public static class CHS
{
/// <summary>Converts a CHS position to a LBA one</summary>
/// <param name="cyl">Cylinder</param>
/// <param name="head">Head</param>
/// <param name="sector">Sector</param>
/// <param name="maxHead">Number of heads</param>
/// <param name="maxSector">Number of sectors per track</param>
/// <returns></returns>
public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) =>
maxHead == 0 || maxSector == 0 ? (((cyl * 16) + head) * 63) + sector - 1
: (((cyl * maxHead) + head) * maxSector) + sector - 1;
}
/// <summary>Converts a CHS position to a LBA one</summary>
/// <param name="cyl">Cylinder</param>
/// <param name="head">Head</param>
/// <param name="sector">Sector</param>
/// <param name="maxHead">Number of heads</param>
/// <param name="maxSector">Number of sectors per track</param>
/// <returns></returns>
public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) =>
maxHead == 0 || maxSector == 0 ? (((cyl * 16) + head) * 63) + sector - 1
: (((cyl * maxHead) + head) * maxSector) + sector - 1;
}

View File

@@ -30,43 +30,42 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Helpers
namespace Aaru.Helpers;
public static partial class ArrayHelpers
{
public static partial class ArrayHelpers
/// <summary>Compares two byte arrays</summary>
/// <param name="different"><c>true</c> if they are different in any way</param>
/// <param name="sameSize"><c>true</c> if they have the same size</param>
/// <param name="compareArray1">Left array</param>
/// <param name="compareArray2">Right array</param>
public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1,
byte[] compareArray2)
{
/// <summary>Compares two byte arrays</summary>
/// <param name="different"><c>true</c> if they are different in any way</param>
/// <param name="sameSize"><c>true</c> if they have the same size</param>
/// <param name="compareArray1">Left array</param>
/// <param name="compareArray2">Right array</param>
public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1,
byte[] compareArray2)
different = false;
sameSize = true;
long leastBytes;
if(compareArray1.LongLength < compareArray2.LongLength)
{
different = false;
sameSize = true;
long leastBytes;
if(compareArray1.LongLength < compareArray2.LongLength)
{
sameSize = false;
leastBytes = compareArray1.LongLength;
}
else if(compareArray1.LongLength > compareArray2.LongLength)
{
sameSize = false;
leastBytes = compareArray2.LongLength;
}
else
leastBytes = compareArray1.LongLength;
for(long i = 0; i < leastBytes; i++)
if(compareArray1[i] != compareArray2[i])
{
different = true;
return;
}
sameSize = false;
leastBytes = compareArray1.LongLength;
}
else if(compareArray1.LongLength > compareArray2.LongLength)
{
sameSize = false;
leastBytes = compareArray2.LongLength;
}
else
leastBytes = compareArray1.LongLength;
for(long i = 0; i < leastBytes; i++)
if(compareArray1[i] != compareArray2[i])
{
different = true;
return;
}
}
}

View File

@@ -30,20 +30,19 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Helpers
{
/// <summary>Helper operations to count bits</summary>
public static class CountBits
{
/// <summary>Counts the number of bits set to <c>true</c> in a number</summary>
/// <param name="number">Number</param>
/// <returns>Bits set to <c>true</c></returns>
public static int Count(uint number)
{
number -= (number >> 1) & 0x55555555;
number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
namespace Aaru.Helpers;
return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
}
/// <summary>Helper operations to count bits</summary>
public static class CountBits
{
/// <summary>Counts the number of bits set to <c>true</c> in a number</summary>
/// <param name="number">Number</param>
/// <returns>Bits set to <c>true</c></returns>
public static int Count(uint number)
{
number -= (number >> 1) & 0x55555555;
number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
}
}

View File

@@ -34,356 +34,355 @@ using System;
using System.Text;
using Aaru.Console;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Helper operations for timestamp management (date and time)</summary>
public static class DateHandlers
{
/// <summary>Helper operations for timestamp management (date and time)</summary>
public static class DateHandlers
static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>Day 0 of Julian Date system</summary>
static readonly DateTime _julianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
static readonly DateTime _amigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
/// <summary>Converts a Macintosh timestamp to a .NET DateTime</summary>
/// <param name="macTimeStamp">Macintosh timestamp (seconds since 1st Jan. 1904)</param>
/// <returns>.NET DateTime</returns>
public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000));
/// <summary>Converts a Lisa timestamp to a .NET DateTime</summary>
/// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param>
/// <returns>.NET DateTime</returns>
public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="seconds">Seconds since 1st Jan. 1970)</param>
/// <param name="nanoseconds">Nanoseconds</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
_unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a High Sierra Format timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">High Sierra Format timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime HighSierraToDateTime(byte[] vdDateTime)
{
static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>Day 0 of Julian Date system</summary>
static readonly DateTime _julianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
static readonly DateTime _amigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
byte[] isoTime = new byte[17];
Array.Copy(vdDateTime, 0, isoTime, 0, 16);
/// <summary>Converts a Macintosh timestamp to a .NET DateTime</summary>
/// <param name="macTimeStamp">Macintosh timestamp (seconds since 1st Jan. 1904)</param>
/// <returns>.NET DateTime</returns>
public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000));
return Iso9660ToDateTime(isoTime);
}
/// <summary>Converts a Lisa timestamp to a .NET DateTime</summary>
/// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param>
/// <returns>.NET DateTime</returns>
public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp);
// TODO: Timezone
/// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">ISO9660 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
{
byte[] twoCharValue = new byte[2];
byte[] fourCharValue = new byte[4];
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
fourCharValue[0] = vdDateTime[0];
fourCharValue[1] = vdDateTime[1];
fourCharValue[2] = vdDateTime[2];
fourCharValue[3] = vdDateTime[3];
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
StringHandlers.CToString(fourCharValue, Encoding.ASCII));
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year))
year = 0;
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="seconds">Seconds since 1st Jan. 1970)</param>
/// <param name="nanoseconds">Nanoseconds</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
_unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
twoCharValue[0] = vdDateTime[4];
twoCharValue[1] = vdDateTime[5];
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
/// <summary>Converts a High Sierra Format timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">High Sierra Format timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime HighSierraToDateTime(byte[] vdDateTime)
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month))
month = 0;
twoCharValue[0] = vdDateTime[6];
twoCharValue[1] = vdDateTime[7];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day))
day = 0;
twoCharValue[0] = vdDateTime[8];
twoCharValue[1] = vdDateTime[9];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour))
hour = 0;
twoCharValue[0] = vdDateTime[10];
twoCharValue[1] = vdDateTime[11];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute))
minute = 0;
twoCharValue[0] = vdDateTime[12];
twoCharValue[1] = vdDateTime[13];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second))
second = 0;
twoCharValue[0] = vdDateTime[14];
twoCharValue[1] = vdDateTime[15];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths))
hundredths = 0;
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler",
"decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
year, month, day, hour, minute, second, hundredths * 10);
sbyte difference = (sbyte)vdDateTime[16];
var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc);
return decodedDt.AddMinutes(difference * -15);
}
/// <summary>Converts a VMS timestamp to a .NET DateTime</summary>
/// <param name="vmsDate">VMS timestamp (tenths of microseconds since day 0 of the Julian Date)</param>
/// <returns>.NET DateTime</returns>
/// <remarks>C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC</remarks>
public static DateTime VmsToDateTime(ulong vmsDate)
{
double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
return _julianEpoch.AddMilliseconds(delta);
}
/// <summary>Converts an Amiga timestamp to a .NET DateTime</summary>
/// <param name="days">Days since the 1st Jan. 1978</param>
/// <param name="minutes">Minutes since o'clock</param>
/// <param name="ticks">Ticks</param>
/// <returns>.NET DateTime</returns>
public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks)
{
DateTime temp = _amigaEpoch.AddDays(days);
temp = temp.AddMinutes(minutes);
return temp.AddMilliseconds(ticks * 20);
}
/// <summary>Converts an UCSD Pascal timestamp to a .NET DateTime</summary>
/// <param name="dateRecord">UCSD Pascal timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UcsdPascalToDateTime(short dateRecord)
{
int year = ((dateRecord & 0xFE00) >> 9) + 1900;
int day = (dateRecord & 0x01F0) >> 4;
int month = dateRecord & 0x000F;
AaruConsole.DebugWriteLine("UCSDPascalToDateTime handler",
"dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year,
month, day);
return new DateTime(year, month, day);
}
/// <summary>Converts a DOS timestamp to a .NET DateTime</summary>
/// <param name="date">Date</param>
/// <param name="time">Time</param>
/// <returns>.NET DateTime</returns>
public static DateTime DosToDateTime(ushort date, ushort time)
{
int year = ((date & 0xFE00) >> 9) + 1980;
int month = (date & 0x1E0) >> 5;
int day = date & 0x1F;
int hour = (time & 0xF800) >> 11;
int minute = (time & 0x7E0) >> 5;
int second = (time & 0x1F) * 2;
AaruConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}",
date, year, month, day);
AaruConsole.DebugWriteLine("DOSToDateTime handler",
"time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute,
second);
DateTime dosDate;
try
{
byte[] isoTime = new byte[17];
Array.Copy(vdDateTime, 0, isoTime, 0, 16);
return Iso9660ToDateTime(isoTime);
dosDate = new DateTime(year, month, day, hour, minute, second);
}
catch(ArgumentOutOfRangeException)
{
dosDate = new DateTime(1980, 1, 1, 0, 0, 0);
}
// TODO: Timezone
/// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">ISO9660 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
return dosDate;
}
/// <summary>Converts a CP/M timestamp to .NET DateTime</summary>
/// <param name="timestamp">CP/M timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime CpmToDateTime(byte[] timestamp)
{
ushort days = BitConverter.ToUInt16(timestamp, 0);
int hours = timestamp[2];
int minutes = timestamp[3];
DateTime temp = _amigaEpoch.AddDays(days);
temp = temp.AddHours(hours);
temp = temp.AddMinutes(minutes);
return temp;
}
/// <summary>Converts an ECMA timestamp to a .NET DateTime</summary>
/// <param name="typeAndTimeZone">Timezone</param>
/// <param name="year">Year</param>
/// <param name="month">Month</param>
/// <param name="day">Day</param>
/// <param name="hour">Hour</param>
/// <param name="minute">Minute</param>
/// <param name="second">Second</param>
/// <param name="centiseconds">Centiseconds</param>
/// <param name="hundredsOfMicroseconds">Hundreds of microseconds</param>
/// <param name="microseconds">Microseconds</param>
/// <returns></returns>
public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour,
byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds,
byte microseconds)
{
byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12);
long ticks = ((long)centiseconds * 100000) + ((long)hundredsOfMicroseconds * 1000) +
((long)microseconds * 10);
if(specification == 0)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks);
ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF);
short offset;
if((preOffset & 0x800) == 0x800)
offset = (short)(preOffset | 0xF000);
else
offset = (short)(preOffset & 0x7FF);
if(offset == -2047)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks);
if(offset < -1440 ||
offset > 1440)
offset = 0;
return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).
AddTicks(ticks).DateTime;
}
/// <summary>Converts a Solaris high resolution timestamp to .NET DateTime</summary>
/// <param name="hrTimeStamp">Solaris high resolution timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) =>
_unixEpoch.AddTicks((long)(hrTimeStamp / 100));
/// <summary>Converts an OS-9 timestamp to .NET DateTime</summary>
/// <param name="date">OS-9 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Os9ToDateTime(byte[] date)
{
if(date == null ||
(date.Length != 3 && date.Length != 5))
return DateTime.MinValue;
DateTime os9Date;
try
{
byte[] twoCharValue = new byte[2];
byte[] fourCharValue = new byte[4];
fourCharValue[0] = vdDateTime[0];
fourCharValue[1] = vdDateTime[1];
fourCharValue[2] = vdDateTime[2];
fourCharValue[3] = vdDateTime[3];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
StringHandlers.CToString(fourCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year))
year = 0;
twoCharValue[0] = vdDateTime[4];
twoCharValue[1] = vdDateTime[5];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month))
month = 0;
twoCharValue[0] = vdDateTime[6];
twoCharValue[1] = vdDateTime[7];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day))
day = 0;
twoCharValue[0] = vdDateTime[8];
twoCharValue[1] = vdDateTime[9];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour))
hour = 0;
twoCharValue[0] = vdDateTime[10];
twoCharValue[1] = vdDateTime[11];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute))
minute = 0;
twoCharValue[0] = vdDateTime[12];
twoCharValue[1] = vdDateTime[13];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second))
second = 0;
twoCharValue[0] = vdDateTime[14];
twoCharValue[1] = vdDateTime[15];
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
StringHandlers.CToString(twoCharValue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths))
hundredths = 0;
AaruConsole.DebugWriteLine("ISO9600ToDateTime handler",
"decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
year, month, day, hour, minute, second, hundredths * 10);
sbyte difference = (sbyte)vdDateTime[16];
var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc);
return decodedDt.AddMinutes(difference * -15);
os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0)
: new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
}
catch(ArgumentOutOfRangeException)
{
os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
}
/// <summary>Converts a VMS timestamp to a .NET DateTime</summary>
/// <param name="vmsDate">VMS timestamp (tenths of microseconds since day 0 of the Julian Date)</param>
/// <returns>.NET DateTime</returns>
/// <remarks>C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC</remarks>
public static DateTime VmsToDateTime(ulong vmsDate)
return os9Date;
}
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="date">LIF timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte[] date)
{
if(date == null ||
date.Length != 6)
return new DateTime(1970, 1, 1, 0, 0, 0);
return LifToDateTime(date[0], date[1], date[2], date[3], date[4], date[5]);
}
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="year">Yer</param>
/// <param name="month">Month</param>
/// <param name="day">Day</param>
/// <param name="hour">Hour</param>
/// <param name="minute">Minute</param>
/// <param name="second">Second</param>
/// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte year, byte month, byte day, byte hour, byte minute, byte second)
{
try
{
double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
int iyear = ((year >> 4) * 10) + (year & 0xF);
int imonth = ((month >> 4) * 10) + (month & 0xF);
int iday = ((day >> 4) * 10) + (day & 0xF);
int iminute = ((minute >> 4) * 10) + (minute & 0xF);
int ihour = ((hour >> 4) * 10) + (hour & 0xF);
int isecond = ((second >> 4) * 10) + (second & 0xF);
return _julianEpoch.AddMilliseconds(delta);
}
/// <summary>Converts an Amiga timestamp to a .NET DateTime</summary>
/// <param name="days">Days since the 1st Jan. 1978</param>
/// <param name="minutes">Minutes since o'clock</param>
/// <param name="ticks">Ticks</param>
/// <returns>.NET DateTime</returns>
public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks)
{
DateTime temp = _amigaEpoch.AddDays(days);
temp = temp.AddMinutes(minutes);
return temp.AddMilliseconds(ticks * 20);
}
/// <summary>Converts an UCSD Pascal timestamp to a .NET DateTime</summary>
/// <param name="dateRecord">UCSD Pascal timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UcsdPascalToDateTime(short dateRecord)
{
int year = ((dateRecord & 0xFE00) >> 9) + 1900;
int day = (dateRecord & 0x01F0) >> 4;
int month = dateRecord & 0x000F;
AaruConsole.DebugWriteLine("UCSDPascalToDateTime handler",
"dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year,
month, day);
return new DateTime(year, month, day);
}
/// <summary>Converts a DOS timestamp to a .NET DateTime</summary>
/// <param name="date">Date</param>
/// <param name="time">Time</param>
/// <returns>.NET DateTime</returns>
public static DateTime DosToDateTime(ushort date, ushort time)
{
int year = ((date & 0xFE00) >> 9) + 1980;
int month = (date & 0x1E0) >> 5;
int day = date & 0x1F;
int hour = (time & 0xF800) >> 11;
int minute = (time & 0x7E0) >> 5;
int second = (time & 0x1F) * 2;
AaruConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}",
date, year, month, day);
AaruConsole.DebugWriteLine("DOSToDateTime handler",
"time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute,
second);
DateTime dosDate;
try
{
dosDate = new DateTime(year, month, day, hour, minute, second);
}
catch(ArgumentOutOfRangeException)
{
dosDate = new DateTime(1980, 1, 1, 0, 0, 0);
}
return dosDate;
}
/// <summary>Converts a CP/M timestamp to .NET DateTime</summary>
/// <param name="timestamp">CP/M timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime CpmToDateTime(byte[] timestamp)
{
ushort days = BitConverter.ToUInt16(timestamp, 0);
int hours = timestamp[2];
int minutes = timestamp[3];
DateTime temp = _amigaEpoch.AddDays(days);
temp = temp.AddHours(hours);
temp = temp.AddMinutes(minutes);
return temp;
}
/// <summary>Converts an ECMA timestamp to a .NET DateTime</summary>
/// <param name="typeAndTimeZone">Timezone</param>
/// <param name="year">Year</param>
/// <param name="month">Month</param>
/// <param name="day">Day</param>
/// <param name="hour">Hour</param>
/// <param name="minute">Minute</param>
/// <param name="second">Second</param>
/// <param name="centiseconds">Centiseconds</param>
/// <param name="hundredsOfMicroseconds">Hundreds of microseconds</param>
/// <param name="microseconds">Microseconds</param>
/// <returns></returns>
public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour,
byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds,
byte microseconds)
{
byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12);
long ticks = ((long)centiseconds * 100000) + ((long)hundredsOfMicroseconds * 1000) +
((long)microseconds * 10);
if(specification == 0)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks);
ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF);
short offset;
if((preOffset & 0x800) == 0x800)
offset = (short)(preOffset | 0xF000);
if(iyear >= 70)
iyear += 1900;
else
offset = (short)(preOffset & 0x7FF);
iyear += 2000;
if(offset == -2047)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks);
if(offset < -1440 ||
offset > 1440)
offset = 0;
return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).
AddTicks(ticks).DateTime;
return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
}
/// <summary>Converts a Solaris high resolution timestamp to .NET DateTime</summary>
/// <param name="hrTimeStamp">Solaris high resolution timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) =>
_unixEpoch.AddTicks((long)(hrTimeStamp / 100));
/// <summary>Converts an OS-9 timestamp to .NET DateTime</summary>
/// <param name="date">OS-9 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Os9ToDateTime(byte[] date)
catch(ArgumentOutOfRangeException)
{
if(date == null ||
(date.Length != 3 && date.Length != 5))
return DateTime.MinValue;
DateTime os9Date;
try
{
os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0)
: new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
}
catch(ArgumentOutOfRangeException)
{
os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
}
return os9Date;
}
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="date">LIF timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte[] date)
{
if(date == null ||
date.Length != 6)
return new DateTime(1970, 1, 1, 0, 0, 0);
return LifToDateTime(date[0], date[1], date[2], date[3], date[4], date[5]);
}
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="year">Yer</param>
/// <param name="month">Month</param>
/// <param name="day">Day</param>
/// <param name="hour">Hour</param>
/// <param name="minute">Minute</param>
/// <param name="second">Second</param>
/// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte year, byte month, byte day, byte hour, byte minute, byte second)
{
try
{
int iyear = ((year >> 4) * 10) + (year & 0xF);
int imonth = ((month >> 4) * 10) + (month & 0xF);
int iday = ((day >> 4) * 10) + (day & 0xF);
int iminute = ((minute >> 4) * 10) + (minute & 0xF);
int ihour = ((hour >> 4) * 10) + (hour & 0xF);
int isecond = ((second >> 4) * 10) + (second & 0xF);
if(iyear >= 70)
iyear += 1900;
else
iyear += 2000;
return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
}
catch(ArgumentOutOfRangeException)
{
return new DateTime(1970, 1, 1, 0, 0, 0);
}
return new DateTime(1970, 1, 1, 0, 0, 0);
}
}
}

View File

@@ -36,463 +36,462 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Provides methods to marshal binary data into C# structs</summary>
public static class Marshal
{
/// <summary>Provides methods to marshal binary data into C# structs</summary>
public static class Marshal
/// <summary>Returns the size of an unmanaged type in bytes.</summary>
/// <typeparam name="T">The type whose size is to be returned.</typeparam>
/// <returns>The size, in bytes, of the type that is specified by the <see cref="T" /> generic type parameter.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>() => System.Runtime.InteropServices.Marshal.SizeOf<T>();
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct
{
/// <summary>Returns the size of an unmanaged type in bytes.</summary>
/// <typeparam name="T">The type whose size is to be returned.</typeparam>
/// <returns>The size, in bytes, of the type that is specified by the <see cref="T" /> generic type parameter.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>() => System.Runtime.InteropServices.Marshal.SizeOf<T>();
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct
var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return str;
}
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureLittleEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T : struct
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return (T)SwapStructureMembersEndian(str);
}
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureBigEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes) where T : struct
{
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
object str =
(T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return str;
}
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureLittleEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T : struct
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return (T)SwapStructureMembersEndian(str);
}
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureBigEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes) where T : struct
{
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str =
(T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return (T)SwapStructureMembersEndianPdp(str);
}
}
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct =>
MemoryMarshal.Read<T>(bytes);
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length)
where T : struct => MemoryMarshal.Read<T>(bytes.Slice(start, length));
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
T str = SpanToStructureLittleEndian<T>(bytes);
return (T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
T str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes);
return (T)SwapStructureMembersEndianPdp(str);
}
/// <summary>
/// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T)SwapStructureMembersEndianPdp(str);
}
/// <summary>
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the
/// decoration is not present it will marshal as a reference type containing little endian structure.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The <see cref="MarshallingPropertiesAttribute" /> contains an unsupported
/// endian
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T MarshalStructure<T>(byte[] bytes) where T : struct
{
if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
properties))
return ByteArrayToStructureLittleEndian<T>(bytes);
switch(properties.Endian)
{
case BitEndian.Little:
return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
: SpanToStructureLittleEndian<T>(bytes);
case BitEndian.Big:
return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes)
: SpanToStructureBigEndian<T>(bytes);
case BitEndian.Pdp:
return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes)
: SpanToStructurePdpEndian<T>(bytes);
default: throw new ArgumentOutOfRangeException();
}
}
/// <summary>Swaps all members of a structure</summary>
/// <param name="str"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")]
public static object SwapStructureMembersEndian(object str)
{
Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
foreach(FieldInfo fi in fieldInfo)
if(fi.FieldType == typeof(short) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)))
{
short x = (short)fi.GetValue(str);
fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
}
else if(fi.FieldType == typeof(int) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
{
int x = (int)fi.GetValue(str);
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
}
else if(fi.FieldType == typeof(long) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)))
{
long x = (long)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x);
}
else if(fi.FieldType == typeof(ushort) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)))
{
ushort x = (ushort)fi.GetValue(str);
fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
}
else if(fi.FieldType == typeof(uint) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
{
uint x = (uint)fi.GetValue(str);
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
fi.SetValue(str, (x << 16) | (x >> 16));
}
else if(fi.FieldType == typeof(ulong) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
{
ulong x = (ulong)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x);
}
else if(fi.FieldType == typeof(float))
{
float flt = (float)fi.GetValue(str);
byte[] flt_b = BitConverter.GetBytes(flt);
fi.SetValue(str, BitConverter.ToSingle(new[]
{
flt_b[3], flt_b[2], flt_b[1], flt_b[0]
}, 0));
}
else if(fi.FieldType == typeof(double))
{
double dbl = (double)fi.GetValue(str);
byte[] dbl_b = BitConverter.GetBytes(dbl);
fi.SetValue(str, BitConverter.ToDouble(new[]
{
dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]
}, 0));
}
else if(fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte))
{
// Do nothing, can't byteswap them!
}
else if(fi.FieldType == typeof(Guid))
{
// TODO: Swap GUID
}
// TODO: Swap arrays
else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndian(obj);
fi.SetValue(str, strc);
}
return str;
}
/// <summary>Swaps all fields in an structure considering them to follow PDP endian conventions</summary>
/// <param name="str">Source structure</param>
/// <returns>Resulting structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndianPdp(object str)
{
Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
foreach(FieldInfo fi in fieldInfo)
if(fi.FieldType == typeof(short) ||
fi.FieldType == typeof(long) ||
fi.FieldType == typeof(ushort) ||
fi.FieldType == typeof(ulong) ||
fi.FieldType == typeof(float) ||
fi.FieldType == typeof(double) ||
fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte) ||
fi.FieldType == typeof(Guid))
{
// Do nothing
}
else if(fi.FieldType == typeof(int) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
{
int x = (int)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
else if(fi.FieldType == typeof(uint) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
{
uint x = (uint)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
// TODO: Swap arrays
else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndianPdp(obj);
fi.SetValue(str, strc);
}
return str;
}
/// <summary>Marshal a structure to little-endian binary data</summary>
/// <param name="str">The structure you want to marshal to binary</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The byte array representing the given structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct
{
byte[] buf = new byte[SizeOf<T>()];
var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
ptr.Free();
return buf;
}
/// <summary>Marshal a structure to little-endian binary data</summary>
/// <param name="str">The structure you want to marshal to binary</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The byte array representing the given structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayBigEndian<T>(T str) where T : struct =>
StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str));
/// <summary>Converts a hexadecimal string into a byte array</summary>
/// <param name="hex">Hexadecimal string</param>
/// <param name="outBuf">Resulting byte array</param>
/// <returns>Number of output bytes processed</returns>
public static int ConvertFromHexAscii(string hex, out byte[] outBuf)
{
outBuf = null;
if(hex is null ||
hex == "")
return -1;
int off = 0;
if(hex[0] == '0' &&
(hex[1] == 'x' || hex[1] == 'X'))
{
off = 2;
}
outBuf = new byte[(hex.Length - off) / 2];
int count = 0;
for(int i = off; i < hex.Length; i += 2)
{
char c = hex[i];
if(c < '0' ||
(c > '9' && c < 'A') ||
(c > 'F' && c < 'a') ||
c > 'f')
break;
c -= c >= 'a' && c <= 'f'
? '\u0057'
: c >= 'A' && c <= 'F'
? '\u0037'
: '\u0030';
outBuf[(i - off) / 2] = (byte)(c << 4);
c = hex[i + 1];
if(c < '0' ||
(c > '9' && c < 'A') ||
(c > 'F' && c < 'a') ||
c > 'f')
break;
c -= c >= 'a' && c <= 'f'
? '\u0057'
: c >= 'A' && c <= 'F'
? '\u0037'
: '\u0030';
outBuf[(i - off) / 2] += (byte)c;
count++;
}
return count;
}
}
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct =>
MemoryMarshal.Read<T>(bytes);
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length)
where T : struct => MemoryMarshal.Read<T>(bytes.Slice(start, length));
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
T str = SpanToStructureLittleEndian<T>(bytes);
return (T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
T str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes);
return (T)SwapStructureMembersEndianPdp(str);
}
/// <summary>
/// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T)SwapStructureMembersEndianPdp(str);
}
/// <summary>
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the
/// decoration is not present it will marshal as a reference type containing little endian structure.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The <see cref="MarshallingPropertiesAttribute" /> contains an unsupported
/// endian
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T MarshalStructure<T>(byte[] bytes) where T : struct
{
if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
properties))
return ByteArrayToStructureLittleEndian<T>(bytes);
switch(properties.Endian)
{
case BitEndian.Little:
return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
: SpanToStructureLittleEndian<T>(bytes);
case BitEndian.Big:
return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes)
: SpanToStructureBigEndian<T>(bytes);
case BitEndian.Pdp:
return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes)
: SpanToStructurePdpEndian<T>(bytes);
default: throw new ArgumentOutOfRangeException();
}
}
/// <summary>Swaps all members of a structure</summary>
/// <param name="str"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")]
public static object SwapStructureMembersEndian(object str)
{
Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
foreach(FieldInfo fi in fieldInfo)
if(fi.FieldType == typeof(short) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)))
{
short x = (short)fi.GetValue(str);
fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
}
else if(fi.FieldType == typeof(int) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
{
int x = (int)fi.GetValue(str);
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
}
else if(fi.FieldType == typeof(long) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)))
{
long x = (long)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x);
}
else if(fi.FieldType == typeof(ushort) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)))
{
ushort x = (ushort)fi.GetValue(str);
fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
}
else if(fi.FieldType == typeof(uint) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
{
uint x = (uint)fi.GetValue(str);
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
fi.SetValue(str, (x << 16) | (x >> 16));
}
else if(fi.FieldType == typeof(ulong) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
{
ulong x = (ulong)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x);
}
else if(fi.FieldType == typeof(float))
{
float flt = (float)fi.GetValue(str);
byte[] flt_b = BitConverter.GetBytes(flt);
fi.SetValue(str, BitConverter.ToSingle(new[]
{
flt_b[3], flt_b[2], flt_b[1], flt_b[0]
}, 0));
}
else if(fi.FieldType == typeof(double))
{
double dbl = (double)fi.GetValue(str);
byte[] dbl_b = BitConverter.GetBytes(dbl);
fi.SetValue(str, BitConverter.ToDouble(new[]
{
dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]
}, 0));
}
else if(fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte))
{
// Do nothing, can't byteswap them!
}
else if(fi.FieldType == typeof(Guid))
{
// TODO: Swap GUID
}
// TODO: Swap arrays
else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndian(obj);
fi.SetValue(str, strc);
}
return str;
}
/// <summary>Swaps all fields in an structure considering them to follow PDP endian conventions</summary>
/// <param name="str">Source structure</param>
/// <returns>Resulting structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndianPdp(object str)
{
Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
foreach(FieldInfo fi in fieldInfo)
if(fi.FieldType == typeof(short) ||
fi.FieldType == typeof(long) ||
fi.FieldType == typeof(ushort) ||
fi.FieldType == typeof(ulong) ||
fi.FieldType == typeof(float) ||
fi.FieldType == typeof(double) ||
fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte) ||
fi.FieldType == typeof(Guid))
{
// Do nothing
}
else if(fi.FieldType == typeof(int) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
{
int x = (int)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
else if(fi.FieldType == typeof(uint) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
{
uint x = (uint)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
// TODO: Swap arrays
else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndianPdp(obj);
fi.SetValue(str, strc);
}
return str;
}
/// <summary>Marshal a structure to little-endian binary data</summary>
/// <param name="str">The structure you want to marshal to binary</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The byte array representing the given structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct
{
byte[] buf = new byte[SizeOf<T>()];
var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
ptr.Free();
return buf;
}
/// <summary>Marshal a structure to little-endian binary data</summary>
/// <param name="str">The structure you want to marshal to binary</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The byte array representing the given structure</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayBigEndian<T>(T str) where T : struct =>
StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str));
/// <summary>Converts a hexadecimal string into a byte array</summary>
/// <param name="hex">Hexadecimal string</param>
/// <param name="outBuf">Resulting byte array</param>
/// <returns>Number of output bytes processed</returns>
public static int ConvertFromHexAscii(string hex, out byte[] outBuf)
{
outBuf = null;
if(hex is null ||
hex == "")
return -1;
int off = 0;
if(hex[0] == '0' &&
(hex[1] == 'x' || hex[1] == 'X'))
{
off = 2;
}
outBuf = new byte[(hex.Length - off) / 2];
int count = 0;
for(int i = off; i < hex.Length; i += 2)
{
char c = hex[i];
if(c < '0' ||
(c > '9' && c < 'A') ||
(c > 'F' && c < 'a') ||
c > 'f')
break;
c -= c >= 'a' && c <= 'f'
? '\u0057'
: c >= 'A' && c <= 'F'
? '\u0037'
: '\u0030';
outBuf[(i - off) / 2] = (byte)(c << 4);
c = hex[i + 1];
if(c < '0' ||
(c > '9' && c < 'A') ||
(c > 'F' && c < 'a') ||
c > 'f')
break;
c -= c >= 'a' && c <= 'f'
? '\u0057'
: c >= 'A' && c <= 'F'
? '\u0037'
: '\u0030';
outBuf[(i - off) / 2] += (byte)c;
count++;
}
return count;
}
}

View File

@@ -38,25 +38,24 @@
using System;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <inheritdoc />
/// <summary>Defines properties to help marshalling structs from binary data</summary>
[AttributeUsage(AttributeTargets.Struct)]
public sealed class MarshallingPropertiesAttribute : Attribute
{
/// <inheritdoc />
/// <summary>Defines properties to help marshalling structs from binary data</summary>
[AttributeUsage(AttributeTargets.Struct)]
public sealed class MarshallingPropertiesAttribute : Attribute
/// <param name="endian">Defines properties to help marshalling structs from binary data</param>
public MarshallingPropertiesAttribute(BitEndian endian)
{
/// <inheritdoc />
/// <summary>Defines properties to help marshalling structs from binary data</summary>
/// <param name="endian">Defines properties to help marshalling structs from binary data</param>
public MarshallingPropertiesAttribute(BitEndian endian)
{
Endian = endian;
HasReferences = true;
}
/// <summary>c</summary>
public BitEndian Endian { get; }
/// <summary>Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc).</summary>
public bool HasReferences { get; set; }
Endian = endian;
HasReferences = true;
}
/// <summary>c</summary>
public BitEndian Endian { get; }
/// <summary>Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc).</summary>
public bool HasReferences { get; set; }
}

View File

@@ -33,104 +33,103 @@
using System.Text;
using Aaru.Console;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Helper operations to get hexadecimal representations of byte arrays</summary>
public static class PrintHex
{
/// <summary>Helper operations to get hexadecimal representations of byte arrays</summary>
public static class PrintHex
/// <summary>Prints a byte array as hexadecimal values to the console</summary>
/// <param name="array">Array</param>
/// <param name="width">Width of line</param>
public static void PrintHexArray(byte[] array, int width = 16) =>
AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width));
/// <summary>Prints a byte array as hexadecimal values to a string</summary>
/// <param name="array">Array</param>
/// <param name="width">Width of line</param>
/// <param name="color">Use ANSI escape colors for sections</param>
/// <returns>String containing hexadecimal values</returns>
public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false)
{
/// <summary>Prints a byte array as hexadecimal values to the console</summary>
/// <param name="array">Array</param>
/// <param name="width">Width of line</param>
public static void PrintHexArray(byte[] array, int width = 16) =>
AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width));
if(array is null)
return null;
/// <summary>Prints a byte array as hexadecimal values to a string</summary>
/// <param name="array">Array</param>
/// <param name="width">Width of line</param>
/// <param name="color">Use ANSI escape colors for sections</param>
/// <returns>String containing hexadecimal values</returns>
public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false)
// TODO: Color list
// TODO: Allow to change width
string str = "Offset";
int rows = array.Length / 16;
int last = array.Length % 16;
int offsetLength = $"{array.Length:X}".Length;
var sb = new StringBuilder();
if(last > 0)
rows++;
if(last == 0)
last = 16;
if(offsetLength < str.Length)
offsetLength = str.Length;
while(str.Length < offsetLength)
str += ' ';
if(color)
sb.Append("\u001b[36m");
sb.Append(str);
sb.Append(" ");
for(int i = 0; i < 16; i++)
{
if(array is null)
return null;
sb.AppendFormat(" {0:X2}", i);
}
// TODO: Color list
// TODO: Allow to change width
string str = "Offset";
int rows = array.Length / 16;
int last = array.Length % 16;
int offsetLength = $"{array.Length:X}".Length;
var sb = new StringBuilder();
if(color)
sb.Append("\u001b[0m");
if(last > 0)
rows++;
sb.AppendLine();
if(last == 0)
last = 16;
int b = 0;
if(offsetLength < str.Length)
offsetLength = str.Length;
while(str.Length < offsetLength)
str += ' ';
string format = $"{{0:X{offsetLength}}}";
for(int i = 0; i < rows; i++)
{
if(color)
sb.Append("\u001b[36m");
sb.Append(str);
sb.Append(" ");
for(int i = 0; i < 16; i++)
{
sb.AppendFormat(" {0:X2}", i);
}
sb.AppendFormat(format, b);
if(color)
sb.Append("\u001b[0m");
sb.AppendLine();
sb.Append(" ");
int lastBytes = i == rows - 1 ? last : 16;
int lastSpaces = 16 - lastBytes;
int b = 0;
string format = $"{{0:X{offsetLength}}}";
for(int i = 0; i < rows; i++)
for(int j = 0; j < lastBytes; j++)
{
if(color)
sb.Append("\u001b[36m");
sb.AppendFormat(format, b);
if(color)
sb.Append("\u001b[0m");
sb.Append(" ");
int lastBytes = i == rows - 1 ? last : 16;
int lastSpaces = 16 - lastBytes;
for(int j = 0; j < lastBytes; j++)
{
sb.AppendFormat(" {0:X2}", array[b]);
b++;
}
for(int j = 0; j < lastSpaces; j++)
sb.Append(" ");
b -= lastBytes;
sb.Append(" ");
for(int j = 0; j < lastBytes; j++)
{
int v = array[b];
sb.Append((v > 31 && v < 127) || v > 159 ? (char)v : '.');
b++;
}
sb.AppendLine();
sb.AppendFormat(" {0:X2}", array[b]);
b++;
}
return sb.ToString();
for(int j = 0; j < lastSpaces; j++)
sb.Append(" ");
b -= lastBytes;
sb.Append(" ");
for(int j = 0; j < lastBytes; j++)
{
int v = array[b];
sb.Append((v > 31 && v < 127) || v > 159 ? (char)v : '.');
b++;
}
sb.AppendLine();
}
return sb.ToString();
}
}

View File

@@ -33,153 +33,152 @@
using System;
using System.Text;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Helper operations to work with strings</summary>
public static class StringHandlers
{
/// <summary>Helper operations to work with strings</summary>
public static class StringHandlers
/// <summary>Converts a null-terminated (aka C string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="cString">A null-terminated (aka C string) ASCII byte array</param>
public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII);
/// <summary>Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="cString">A null-terminated (aka C string) byte array in the specified encoding</param>
/// <param name="encoding">Encoding.</param>
/// <param name="twoBytes">Set if encoding uses 16-bit characters.</param>
/// <param name="start">Start decoding at this position</param>
public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0)
{
/// <summary>Converts a null-terminated (aka C string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="cString">A null-terminated (aka C string) ASCII byte array</param>
public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII);
if(cString == null)
return null;
/// <summary>Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="cString">A null-terminated (aka C string) byte array in the specified encoding</param>
/// <param name="encoding">Encoding.</param>
/// <param name="twoBytes">Set if encoding uses 16-bit characters.</param>
/// <param name="start">Start decoding at this position</param>
public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0)
int len = 0;
for(int i = start; i < cString.Length; i++)
{
if(cString == null)
return null;
int len = 0;
for(int i = start; i < cString.Length; i++)
{
if(cString[i] == 0)
if(twoBytes)
if(cString[i] == 0)
if(twoBytes)
{
if(i + 1 < cString.Length &&
cString[i + 1] == 0)
{
if(i + 1 < cString.Length &&
cString[i + 1] == 0)
{
len++;
len++;
break;
}
}
else
break;
len++;
}
if(twoBytes && len % 2 > 0)
len--;
byte[] dest = new byte[len];
Array.Copy(cString, start, dest, 0, len);
return len == 0 ? "" : encoding.GetString(dest);
}
/// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="pascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII);
/// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="pascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
/// <param name="encoding">Encoding.</param>
/// <param name="start">Start decoding at this position</param>
public static string PascalToString(byte[] pascalString, Encoding encoding, int start = 0)
{
if(pascalString == null)
return null;
byte length = pascalString[start];
int len = 0;
for(int i = start + 1; i < length + 1 && i < pascalString.Length; i++)
{
if(pascalString[i] == 0)
break;
len++;
}
byte[] dest = new byte[len];
Array.Copy(pascalString, start + 1, dest, 0, len);
return len == 0 ? "" : encoding.GetString(dest);
}
/// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="spacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
public static string SpacePaddedToString(byte[] spacePaddedString) =>
SpacePaddedToString(spacePaddedString, Encoding.ASCII);
/// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="spacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
/// <param name="encoding">Encoding.</param>
/// <param name="start">Start decoding at this position</param>
public static string SpacePaddedToString(byte[] spacePaddedString, Encoding encoding, int start = 0)
{
if(spacePaddedString == null)
return null;
int len = start;
for(int i = spacePaddedString.Length; i >= start; i--)
{
if(i == start)
return "";
if(spacePaddedString[i - 1] == 0x20)
continue;
len = i;
break;
}
return len == 0 ? "" : encoding.GetString(spacePaddedString, start, len);
}
/// <summary>Converts an OSTA compressed unicode byte array to a C# string</summary>
/// <returns>The C# string.</returns>
/// <param name="dstring">OSTA compressed unicode byte array.</param>
public static string DecompressUnicode(byte[] dstring)
{
ushort unicode;
byte compId = dstring[0];
string temp = "";
if(compId != 8 &&
compId != 16)
return null;
for(int byteIndex = 1; byteIndex < dstring.Length;)
{
if(compId == 16)
unicode = (ushort)(dstring[byteIndex++] << 8);
}
}
else
unicode = 0;
if(byteIndex < dstring.Length)
unicode |= dstring[byteIndex++];
if(unicode == 0)
break;
temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode));
}
return temp;
len++;
}
if(twoBytes && len % 2 > 0)
len--;
byte[] dest = new byte[len];
Array.Copy(cString, start, dest, 0, len);
return len == 0 ? "" : encoding.GetString(dest);
}
/// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="pascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII);
/// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="pascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
/// <param name="encoding">Encoding.</param>
/// <param name="start">Start decoding at this position</param>
public static string PascalToString(byte[] pascalString, Encoding encoding, int start = 0)
{
if(pascalString == null)
return null;
byte length = pascalString[start];
int len = 0;
for(int i = start + 1; i < length + 1 && i < pascalString.Length; i++)
{
if(pascalString[i] == 0)
break;
len++;
}
byte[] dest = new byte[len];
Array.Copy(pascalString, start + 1, dest, 0, len);
return len == 0 ? "" : encoding.GetString(dest);
}
/// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="spacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
public static string SpacePaddedToString(byte[] spacePaddedString) =>
SpacePaddedToString(spacePaddedString, Encoding.ASCII);
/// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// <returns>The corresponding C# string</returns>
/// <param name="spacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
/// <param name="encoding">Encoding.</param>
/// <param name="start">Start decoding at this position</param>
public static string SpacePaddedToString(byte[] spacePaddedString, Encoding encoding, int start = 0)
{
if(spacePaddedString == null)
return null;
int len = start;
for(int i = spacePaddedString.Length; i >= start; i--)
{
if(i == start)
return "";
if(spacePaddedString[i - 1] == 0x20)
continue;
len = i;
break;
}
return len == 0 ? "" : encoding.GetString(spacePaddedString, start, len);
}
/// <summary>Converts an OSTA compressed unicode byte array to a C# string</summary>
/// <returns>The C# string.</returns>
/// <param name="dstring">OSTA compressed unicode byte array.</param>
public static string DecompressUnicode(byte[] dstring)
{
ushort unicode;
byte compId = dstring[0];
string temp = "";
if(compId != 8 &&
compId != 16)
return null;
for(int byteIndex = 1; byteIndex < dstring.Length;)
{
if(compId == 16)
unicode = (ushort)(dstring[byteIndex++] << 8);
else
unicode = 0;
if(byteIndex < dstring.Length)
unicode |= dstring[byteIndex++];
if(unicode == 0)
break;
temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode));
}
return temp;
}
}

View File

@@ -32,81 +32,80 @@
using System.Runtime.CompilerServices;
namespace Aaru.Helpers
namespace Aaru.Helpers;
/// <summary>Helper operations to work with swapping endians</summary>
public static class Swapping
{
/// <summary>Helper operations to work with swapping endians</summary>
public static class Swapping
/// <summary>Gets the PDP endian equivalent of the given little endian unsigned integer</summary>
/// <param name="x">Little endian unsigned integer</param>
/// <returns>PDP unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint PDPFromLittleEndian(uint x) => ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
/// <summary>Gets the PDP endian equivalent of the given big endian unsigned integer</summary>
/// <param name="x">Big endian unsigned integer</param>
/// <returns>PDP unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint PDPFromBigEndian(uint x) => ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
/// <summary>Swaps the endian of the specified unsigned short integer</summary>
/// <param name="x">Unsigned short integer</param>
/// <returns>Swapped unsigned short integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8));
/// <summary>Swaps the endian of the specified signed short integer</summary>
/// <param name="x">Signed short integer</param>
/// <returns>Swapped signed short integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Swap(short x) => (short)((x << 8) | ((x >> 8) & 0xFF));
/// <summary>Swaps the endian of the specified unsigned integer</summary>
/// <param name="x">Unsigned integer</param>
/// <returns>Swapped unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Swap(uint x)
{
/// <summary>Gets the PDP endian equivalent of the given little endian unsigned integer</summary>
/// <param name="x">Little endian unsigned integer</param>
/// <returns>PDP unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint PDPFromLittleEndian(uint x) => ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
/// <summary>Gets the PDP endian equivalent of the given big endian unsigned integer</summary>
/// <param name="x">Big endian unsigned integer</param>
/// <returns>PDP unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint PDPFromBigEndian(uint x) => ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
return (x << 16) | (x >> 16);
}
/// <summary>Swaps the endian of the specified unsigned short integer</summary>
/// <param name="x">Unsigned short integer</param>
/// <returns>Swapped unsigned short integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8));
/// <summary>Swaps the endian of the specified signed integer</summary>
/// <param name="x">Signed integer</param>
/// <returns>Swapped signed integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Swap(int x)
{
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
/// <summary>Swaps the endian of the specified signed short integer</summary>
/// <param name="x">Signed short integer</param>
/// <returns>Swapped signed short integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Swap(short x) => (short)((x << 8) | ((x >> 8) & 0xFF));
return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
}
/// <summary>Swaps the endian of the specified unsigned integer</summary>
/// <param name="x">Unsigned integer</param>
/// <returns>Swapped unsigned integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Swap(uint x)
{
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
/// <summary>Swaps the endian of the specified unsigned long integer</summary>
/// <param name="x">Unsigned long integer</param>
/// <returns>Swapped unsigned long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Swap(ulong x)
{
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
return (x << 16) | (x >> 16);
}
return x;
}
/// <summary>Swaps the endian of the specified signed integer</summary>
/// <param name="x">Signed integer</param>
/// <returns>Swapped signed integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Swap(int x)
{
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
/// <summary>Swaps the endian of the specified signed long integer</summary>
/// <param name="x">Signed long integer</param>
/// <returns>Swapped signed long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Swap(long x)
{
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
}
/// <summary>Swaps the endian of the specified unsigned long integer</summary>
/// <param name="x">Unsigned long integer</param>
/// <returns>Swapped unsigned long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Swap(ulong x)
{
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
return x;
}
/// <summary>Swaps the endian of the specified signed long integer</summary>
/// <param name="x">Signed long integer</param>
/// <returns>Swapped signed long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Swap(long x)
{
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
return x;
}
return x;
}
}