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;
using System.Text; 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> value
/// <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
});
/// <summary>Fills an array with the contents of the specified array</summary> /// <summary>Fills an array with the contents of the specified array</summary>
/// <param name="destinationArray">Array</param> /// <param name="destinationArray">Array</param>
/// <param name="value">Value</param> /// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam> /// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T[] value) public static void ArrayFill<T>(T[] destinationArray, T[] value)
{ {
if(destinationArray == null) if(destinationArray == null)
throw new ArgumentNullException(nameof(destinationArray)); throw new ArgumentNullException(nameof(destinationArray));
if(value.Length > destinationArray.Length) if(value.Length > destinationArray.Length)
throw new ArgumentException("Length of value array must not be more than length of destination"); throw new ArgumentException("Length of value array must not be more than length of destination");
// set the initial array value // set the initial array value
Array.Copy(value, destinationArray, value.Length); Array.Copy(value, destinationArray, value.Length);
int arrayToFillHalfLength = destinationArray.Length / 2; int arrayToFillHalfLength = destinationArray.Length / 2;
int copyLength; int copyLength;
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1) for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength); 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> /// <summary>Converts a byte array to its hexadecimal representation</summary>
/// <param name="array">Byte array</param> /// <param name="array">Byte array</param>
/// <param name="upper"><c>true</c> to use uppercase</param> /// <param name="upper"><c>true</c> to use uppercase</param>
/// <returns></returns> /// <returns></returns>
public static string ByteArrayToHex(byte[] array, bool upper = false) public static string ByteArrayToHex(byte[] array, bool upper = false)
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
for(long i = 0; i < array.LongLength; i++) for(long i = 0; i < array.LongLength; i++)
sb.AppendFormat("{0:x2}", array[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; using System.Linq;
namespace Aaru.Helpers 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;
/// <summary>Checks if an array is null or filled with the NULL byte (0x00)</summary> /// <summary>Helper operations to work with arrays</summary>
/// <param name="array">Array</param> public static partial class ArrayHelpers
/// <returns>True if null</returns> {
public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false; /// <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;
using System.Linq; 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> /// <summary>
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from /// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration. /// array.
/// </summary> /// </summary>
public static class BigEndianBitConverter /// <param name="value">An array of bytes.</param>
{ /// <param name="startIndex">The starting position within value.</param>
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary> /// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <param name="value">The number to convert.</param> /// <exception cref="System.ArgumentException">
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns> /// <see cref="startIndex" /> is greater than or equal to the length of value
/// <exception cref="NotImplementedException">It is not currently implemented</exception> /// minus 7, and is less than or equal to the length of value minus 1.
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException(); /// </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> /// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">A Boolean value.</param> /// <param name="value">An array of bytes.</param>
/// <returns>An array of bytes with length 1.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">A character to convert.</param> /// <param name="value">An array of bytes.</param>
/// <returns>An array of bytes with length 2.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">The number to convert.</param> /// <param name="value">An array of bytes.</param>
/// <returns>An array of bytes with length 8.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>
/// <param name="value">The number to convert.</param> /// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
/// <returns>An array of bytes with length 4.</returns> /// array.
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// </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> /// <summary>
/// <param name="value">The number to convert.</param> /// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
/// <returns>An array of bytes with length 4.</returns> /// representation.
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// </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> /// <summary>
/// <param name="value">The number to convert.</param> /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// <returns>An array of bytes with length 8.</returns> /// string representation.
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// </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> /// <summary>
/// <param name="value">The number to convert.</param> /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// <returns>An array of bytes with length 2.</returns> /// string representation.
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// </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> /// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The array of bytes.</param>
/// <returns>An array of bytes with length 4.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">The number to convert.</param> /// <param name="value">An array of bytes.</param>
/// <returns>An array of bytes with length 8.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">The number to convert.</param> /// <param name="value">An array of bytes.</param>
/// <returns>An array of bytes with length 2.</returns> /// <param name="startIndex">The starting position within value.</param>
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray(); /// <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> /// <summary>Converts a big endian byte array representation of a GUID into the .NET Guid structure</summary>
/// <param name="value">The number to convert.</param> /// <param name="value">Byte array containing a GUID in big endian</param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns> /// <param name="startIndex">Start of the byte array to process</param>
public static double Int64BitsToDouble(long value) => throw new NotImplementedException(); /// <returns>Processed Guid</returns>
public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary> ToUInt16(value, 4 + startIndex),
/// <param name="value">An array of bytes.</param> ToUInt16(value, 6 + startIndex),
/// <param name="startIndex">The starting position within value.</param> value[8 + startIndex + 0],
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns> value[8 + startIndex + 1],
/// <exception cref="System.ArgumentNullException">value is null.</exception> value[8 + startIndex + 2],
/// <exception cref="System.ArgumentOutOfRangeException"> value[8 + startIndex + 3],
/// <see cref="startIndex" /> is less than zero or greater than the value[8 + startIndex + 5],
/// length of value minus 1. value[8 + startIndex + 5],
/// </exception> value[8 + startIndex + 6],
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException(); value[8 + startIndex + 7]);
/// <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]);
}
} }

View File

@@ -36,16 +36,15 @@
// Copyright © 2011-2022 Natalia Portillo // 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> /// <summary>Little-endian, or least significant bit</summary>
public enum BitEndian Little,
{ /// <summary>Big-endian, or most significant bit</summary>
/// <summary>Little-endian, or least significant bit</summary> Big,
Little, /// <summary>PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them</summary>
/// <summary>Big-endian, or most significant bit</summary> Pdp
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 // 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> /// <summary>Converts a CHS position to a LBA one</summary>
public static class CHS /// <param name="cyl">Cylinder</param>
{ /// <param name="head">Head</param>
/// <summary>Converts a CHS position to a LBA one</summary> /// <param name="sector">Sector</param>
/// <param name="cyl">Cylinder</param> /// <param name="maxHead">Number of heads</param>
/// <param name="head">Head</param> /// <param name="maxSector">Number of sectors per track</param>
/// <param name="sector">Sector</param> /// <returns></returns>
/// <param name="maxHead">Number of heads</param> public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) =>
/// <param name="maxSector">Number of sectors per track</param> maxHead == 0 || maxSector == 0 ? (((cyl * 16) + head) * 63) + sector - 1
/// <returns></returns> : (((cyl * maxHead) + head) * maxSector) + sector - 1;
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 // 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> different = false;
/// <param name="different"><c>true</c> if they are different in any way</param> sameSize = true;
/// <param name="sameSize"><c>true</c> if they have the same size</param>
/// <param name="compareArray1">Left array</param> long leastBytes;
/// <param name="compareArray2">Right array</param>
public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1, if(compareArray1.LongLength < compareArray2.LongLength)
byte[] compareArray2)
{ {
different = false; sameSize = false;
sameSize = true; leastBytes = compareArray1.LongLength;
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;
}
} }
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 // Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
namespace Aaru.Helpers 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);
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 System.Text;
using Aaru.Console; 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> static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
public static class DateHandlers 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); byte[] isoTime = new byte[17];
static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0); Array.Copy(vdDateTime, 0, isoTime, 0, 16);
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> return Iso9660ToDateTime(isoTime);
/// <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> // TODO: Timezone
/// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param> /// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary>
/// <returns>.NET DateTime</returns> /// <param name="vdDateTime">ISO9660 timestamp</param>
public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp); /// <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> fourCharValue[0] = vdDateTime[0];
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> fourCharValue[1] = vdDateTime[1];
/// <returns>.NET DateTime</returns> fourCharValue[2] = vdDateTime[2];
public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); fourCharValue[3] = vdDateTime[3];
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary> AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> StringHandlers.CToString(fourCharValue, Encoding.ASCII));
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary> if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year))
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> year = 0;
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary> twoCharValue[0] = vdDateTime[4];
/// <param name="seconds">Seconds since 1st Jan. 1970)</param> twoCharValue[1] = vdDateTime[5];
/// <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> AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> StringHandlers.CToString(twoCharValue, Encoding.ASCII));
/// <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> if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month))
/// <param name="vdDateTime">High Sierra Format timestamp</param> month = 0;
/// <returns>.NET DateTime</returns>
public static DateTime HighSierraToDateTime(byte[] vdDateTime) 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]; dosDate = new DateTime(year, month, day, hour, minute, second);
Array.Copy(vdDateTime, 0, isoTime, 0, 16); }
catch(ArgumentOutOfRangeException)
return Iso9660ToDateTime(isoTime); {
dosDate = new DateTime(1980, 1, 1, 0, 0, 0);
} }
// TODO: Timezone return dosDate;
/// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary> }
/// <param name="vdDateTime">ISO9660 timestamp</param>
/// <returns>.NET DateTime</returns> /// <summary>Converts a CP/M timestamp to .NET DateTime</summary>
public static DateTime Iso9660ToDateTime(byte[] vdDateTime) /// <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]; os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0)
byte[] fourCharValue = new byte[4]; : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
}
fourCharValue[0] = vdDateTime[0]; catch(ArgumentOutOfRangeException)
fourCharValue[1] = vdDateTime[1]; {
fourCharValue[2] = vdDateTime[2]; os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
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);
} }
/// <summary>Converts a VMS timestamp to a .NET DateTime</summary> return os9Date;
/// <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> /// <summary>Converts a LIF timestamp to .NET DateTime</summary>
public static DateTime VmsToDateTime(ulong vmsDate) /// <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); if(iyear >= 70)
} iyear += 1900;
/// <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);
else else
offset = (short)(preOffset & 0x7FF); iyear += 2000;
if(offset == -2047) return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
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;
} }
catch(ArgumentOutOfRangeException)
/// <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 || return new DateTime(1970, 1, 1, 0, 0, 0);
(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);
}
} }
} }
} }

View File

@@ -36,463 +36,462 @@ using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 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> /// <summary>Returns the size of an unmanaged type in bytes.</summary>
public static class Marshal /// <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> var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
/// <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> var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> ptr.Free();
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] return str;
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct }
/// <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 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(); 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); 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 /// <summary>Marshal PDP-11 binary data to a structure</summary>
/// crash. /// <param name="bytes">Byte array containing the binary data</param>
/// </summary> /// <param name="start">Start on the array where the structure begins</param>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="length">Length of the structure in bytes</param>
/// <param name="start">Start on the span where the structure begins</param> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <param name="length">Length of the structure in bytes</param> /// <returns>The binary data marshalled in a structure with the specified type</returns>
/// <typeparam name="T">Type of the structure to marshal</typeparam> [MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <returns>The binary data marshalled in a structure with the specified type</returns> public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct
[MethodImpl(MethodImplOptions.AggressiveInlining)] {
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct Span<byte> span = bytes;
{
object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length)); return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray());
}
return (T)SwapStructureMembersEndianPdp(str);
} /// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// <summary> /// method will crash.
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the /// </summary>
/// decoration is not present it will marshal as a reference type containing little endian structure. /// <param name="bytes">Byte array containing the binary data</param>
/// </summary> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <param name="bytes">Byte array containing the binary data</param> /// <returns>The binary data marshalled in a structure with the specified type</returns>
/// <typeparam name="T">Type of the structure to marshal</typeparam> [MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <returns>The binary data marshalled in a structure with the specified type</returns> public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct =>
/// <exception cref="ArgumentOutOfRangeException"> MemoryMarshal.Read<T>(bytes);
/// The <see cref="MarshallingPropertiesAttribute" /> contains an unsupported
/// endian /// <summary>
/// </exception> /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
[MethodImpl(MethodImplOptions.AggressiveInlining)] /// method will crash.
public static T MarshalStructure<T>(byte[] bytes) where T : struct /// </summary>
{ /// <param name="bytes">Byte span containing the binary data</param>
if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute /// <param name="start">Start on the span where the structure begins</param>
properties)) /// <param name="length">Length of the structure in bytes</param>
return ByteArrayToStructureLittleEndian<T>(bytes); /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
switch(properties.Endian) [MethodImpl(MethodImplOptions.AggressiveInlining)]
{ public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length)
case BitEndian.Little: where T : struct => MemoryMarshal.Read<T>(bytes.Slice(start, length));
return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
: SpanToStructureLittleEndian<T>(bytes); /// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
case BitEndian.Big: /// will crash.
return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes) /// </summary>
: SpanToStructureBigEndian<T>(bytes); /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
case BitEndian.Pdp: /// <returns>The binary data marshalled in a structure with the specified type</returns>
return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes) [MethodImpl(MethodImplOptions.AggressiveInlining)]
: SpanToStructurePdpEndian<T>(bytes); public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
default: throw new ArgumentOutOfRangeException(); {
} T str = SpanToStructureLittleEndian<T>(bytes);
}
return (T)SwapStructureMembersEndian(str);
/// <summary>Swaps all members of a structure</summary> }
/// <param name="str"></param>
/// <returns></returns> /// <summary>
[MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")] /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
public static object SwapStructureMembersEndian(object str) /// will crash.
{ /// </summary>
Type t = str.GetType(); /// <param name="bytes">Byte span containing the binary data</param>
FieldInfo[] fieldInfo = t.GetFields(); /// <param name="start">Start on the span where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
foreach(FieldInfo fi in fieldInfo) /// <typeparam name="T">Type of the structure to marshal</typeparam>
if(fi.FieldType == typeof(short) || /// <returns>The binary data marshalled in a structure with the specified type</returns>
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short))) [MethodImpl(MethodImplOptions.AggressiveInlining)]
{ public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
short x = (short)fi.GetValue(str); {
fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF))); T str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
}
else if(fi.FieldType == typeof(int) || return (T)SwapStructureMembersEndian(str);
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int))) }
{
int x = (int)fi.GetValue(str); /// <summary>
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF))); /// crash.
} /// </summary>
else if(fi.FieldType == typeof(long) || /// <param name="bytes">Byte array containing the binary data</param>
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long))) /// <typeparam name="T">Type of the structure to marshal</typeparam>
{ /// <returns>The binary data marshalled in a structure with the specified type</returns>
long x = (long)fi.GetValue(str); [MethodImpl(MethodImplOptions.AggressiveInlining)]
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); {
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); object str = SpanToStructureLittleEndian<T>(bytes);
fi.SetValue(str, x); return (T)SwapStructureMembersEndianPdp(str);
} }
else if(fi.FieldType == typeof(ushort) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort))) /// <summary>
{ /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
ushort x = (ushort)fi.GetValue(str); /// crash.
fi.SetValue(str, (ushort)((x << 8) | (x >> 8))); /// </summary>
} /// <param name="bytes">Byte array containing the binary data</param>
else if(fi.FieldType == typeof(uint) || /// <param name="start">Start on the span where the structure begins</param>
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint))) /// <param name="length">Length of the structure in bytes</param>
{ /// <typeparam name="T">Type of the structure to marshal</typeparam>
uint x = (uint)fi.GetValue(str); /// <returns>The binary data marshalled in a structure with the specified type</returns>
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); [MethodImpl(MethodImplOptions.AggressiveInlining)]
fi.SetValue(str, (x << 16) | (x >> 16)); public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
} {
else if(fi.FieldType == typeof(ulong) || object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
{ return (T)SwapStructureMembersEndianPdp(str);
ulong x = (ulong)fi.GetValue(str); }
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); /// <summary>
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); /// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the
fi.SetValue(str, x); /// decoration is not present it will marshal as a reference type containing little endian structure.
} /// </summary>
else if(fi.FieldType == typeof(float)) /// <param name="bytes">Byte array containing the binary data</param>
{ /// <typeparam name="T">Type of the structure to marshal</typeparam>
float flt = (float)fi.GetValue(str); /// <returns>The binary data marshalled in a structure with the specified type</returns>
byte[] flt_b = BitConverter.GetBytes(flt); /// <exception cref="ArgumentOutOfRangeException">
/// The <see cref="MarshallingPropertiesAttribute" /> contains an unsupported
fi.SetValue(str, BitConverter.ToSingle(new[] /// endian
{ /// </exception>
flt_b[3], flt_b[2], flt_b[1], flt_b[0] [MethodImpl(MethodImplOptions.AggressiveInlining)]
}, 0)); public static T MarshalStructure<T>(byte[] bytes) where T : struct
} {
else if(fi.FieldType == typeof(double)) if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
{ properties))
double dbl = (double)fi.GetValue(str); return ByteArrayToStructureLittleEndian<T>(bytes);
byte[] dbl_b = BitConverter.GetBytes(dbl);
switch(properties.Endian)
fi.SetValue(str, BitConverter.ToDouble(new[] {
{ case BitEndian.Little:
dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0] return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
}, 0)); : SpanToStructureLittleEndian<T>(bytes);
}
else if(fi.FieldType == typeof(byte) || case BitEndian.Big:
fi.FieldType == typeof(sbyte)) return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes)
{ : SpanToStructureBigEndian<T>(bytes);
// Do nothing, can't byteswap them!
} case BitEndian.Pdp:
else if(fi.FieldType == typeof(Guid)) return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes)
{ : SpanToStructurePdpEndian<T>(bytes);
// TODO: Swap GUID default: throw new ArgumentOutOfRangeException();
} }
}
// TODO: Swap arrays
else if(fi.FieldType.IsValueType && /// <summary>Swaps all members of a structure</summary>
!fi.FieldType.IsEnum && /// <param name="str"></param>
!fi.FieldType.IsArray) /// <returns></returns>
{ [MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")]
object obj = fi.GetValue(str); public static object SwapStructureMembersEndian(object str)
object strc = SwapStructureMembersEndian(obj); {
fi.SetValue(str, strc); Type t = str.GetType();
} FieldInfo[] fieldInfo = t.GetFields();
return str; foreach(FieldInfo fi in fieldInfo)
} if(fi.FieldType == typeof(short) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)))
/// <summary>Swaps all fields in an structure considering them to follow PDP endian conventions</summary> {
/// <param name="str">Source structure</param> short x = (short)fi.GetValue(str);
/// <returns>Resulting structure</returns> fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
[MethodImpl(MethodImplOptions.AggressiveInlining)] }
public static object SwapStructureMembersEndianPdp(object str) else if(fi.FieldType == typeof(int) ||
{ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
Type t = str.GetType(); {
FieldInfo[] fieldInfo = t.GetFields(); int x = (int)fi.GetValue(str);
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
foreach(FieldInfo fi in fieldInfo) fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
if(fi.FieldType == typeof(short) || }
fi.FieldType == typeof(long) || else if(fi.FieldType == typeof(long) ||
fi.FieldType == typeof(ushort) || (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)))
fi.FieldType == typeof(ulong) || {
fi.FieldType == typeof(float) || long x = (long)fi.GetValue(str);
fi.FieldType == typeof(double) || x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
fi.FieldType == typeof(byte) || x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
fi.FieldType == typeof(sbyte) || x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
fi.FieldType == typeof(Guid))
{ fi.SetValue(str, x);
// Do nothing }
} else if(fi.FieldType == typeof(ushort) ||
else if(fi.FieldType == typeof(int) || (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)))
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int))) {
{ ushort x = (ushort)fi.GetValue(str);
int x = (int)fi.GetValue(str); fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16)); }
} else if(fi.FieldType == typeof(uint) ||
else if(fi.FieldType == typeof(uint) || (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint))) {
{ uint x = (uint)fi.GetValue(str);
uint x = (uint)fi.GetValue(str); x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16)); fi.SetValue(str, (x << 16) | (x >> 16));
} }
else if(fi.FieldType == typeof(ulong) ||
// TODO: Swap arrays (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
else if(fi.FieldType.IsValueType && {
!fi.FieldType.IsEnum && ulong x = (ulong)fi.GetValue(str);
!fi.FieldType.IsArray) x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
{ x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
object obj = fi.GetValue(str); x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
object strc = SwapStructureMembersEndianPdp(obj); fi.SetValue(str, x);
fi.SetValue(str, strc); }
} else if(fi.FieldType == typeof(float))
{
return str; float flt = (float)fi.GetValue(str);
} byte[] flt_b = BitConverter.GetBytes(flt);
/// <summary>Marshal a structure to little-endian binary data</summary> fi.SetValue(str, BitConverter.ToSingle(new[]
/// <param name="str">The structure you want to marshal to binary</param> {
/// <typeparam name="T">Type of the structure to marshal</typeparam> flt_b[3], flt_b[2], flt_b[1], flt_b[0]
/// <returns>The byte array representing the given structure</returns> }, 0));
[MethodImpl(MethodImplOptions.AggressiveInlining)] }
public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct else if(fi.FieldType == typeof(double))
{ {
byte[] buf = new byte[SizeOf<T>()]; double dbl = (double)fi.GetValue(str);
var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned); byte[] dbl_b = BitConverter.GetBytes(dbl);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
ptr.Free(); fi.SetValue(str, BitConverter.ToDouble(new[]
{
return buf; 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));
}
/// <summary>Marshal a structure to little-endian binary data</summary> else if(fi.FieldType == typeof(byte) ||
/// <param name="str">The structure you want to marshal to binary</param> fi.FieldType == typeof(sbyte))
/// <typeparam name="T">Type of the structure to marshal</typeparam> {
/// <returns>The byte array representing the given structure</returns> // Do nothing, can't byteswap them!
[MethodImpl(MethodImplOptions.AggressiveInlining)] }
public static byte[] StructureToByteArrayBigEndian<T>(T str) where T : struct => else if(fi.FieldType == typeof(Guid))
StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str)); {
// TODO: Swap GUID
/// <summary>Converts a hexadecimal string into a byte array</summary> }
/// <param name="hex">Hexadecimal string</param>
/// <param name="outBuf">Resulting byte array</param> // TODO: Swap arrays
/// <returns>Number of output bytes processed</returns> else if(fi.FieldType.IsValueType &&
public static int ConvertFromHexAscii(string hex, out byte[] outBuf) !fi.FieldType.IsEnum &&
{ !fi.FieldType.IsArray)
outBuf = null; {
object obj = fi.GetValue(str);
if(hex is null || object strc = SwapStructureMembersEndian(obj);
hex == "") fi.SetValue(str, strc);
return -1; }
int off = 0; return str;
}
if(hex[0] == '0' &&
(hex[1] == 'x' || hex[1] == 'X')) /// <summary>Swaps all fields in an structure considering them to follow PDP endian conventions</summary>
{ /// <param name="str">Source structure</param>
off = 2; /// <returns>Resulting structure</returns>
} [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndianPdp(object str)
outBuf = new byte[(hex.Length - off) / 2]; {
int count = 0; Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
for(int i = off; i < hex.Length; i += 2)
{ foreach(FieldInfo fi in fieldInfo)
char c = hex[i]; if(fi.FieldType == typeof(short) ||
fi.FieldType == typeof(long) ||
if(c < '0' || fi.FieldType == typeof(ushort) ||
(c > '9' && c < 'A') || fi.FieldType == typeof(ulong) ||
(c > 'F' && c < 'a') || fi.FieldType == typeof(float) ||
c > 'f') fi.FieldType == typeof(double) ||
break; fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte) ||
c -= c >= 'a' && c <= 'f' fi.FieldType == typeof(Guid))
? '\u0057' {
: c >= 'A' && c <= 'F' // Do nothing
? '\u0037' }
: '\u0030'; else if(fi.FieldType == typeof(int) ||
(fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
outBuf[(i - off) / 2] = (byte)(c << 4); {
int x = (int)fi.GetValue(str);
c = hex[i + 1]; fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
if(c < '0' || else if(fi.FieldType == typeof(uint) ||
(c > '9' && c < 'A') || (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
(c > 'F' && c < 'a') || {
c > 'f') uint x = (uint)fi.GetValue(str);
break; fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
}
c -= c >= 'a' && c <= 'f'
? '\u0057' // TODO: Swap arrays
: c >= 'A' && c <= 'F' else if(fi.FieldType.IsValueType &&
? '\u0037' !fi.FieldType.IsEnum &&
: '\u0030'; !fi.FieldType.IsArray)
{
outBuf[(i - off) / 2] += (byte)c; object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndianPdp(obj);
count++; fi.SetValue(str, strc);
} }
return count; 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; 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 /> /// <inheritdoc />
/// <summary>Defines properties to help marshalling structs from binary data</summary> /// <summary>Defines properties to help marshalling structs from binary data</summary>
[AttributeUsage(AttributeTargets.Struct)] /// <param name="endian">Defines properties to help marshalling structs from binary data</param>
public sealed class MarshallingPropertiesAttribute : Attribute public MarshallingPropertiesAttribute(BitEndian endian)
{ {
/// <inheritdoc /> Endian = endian;
/// <summary>Defines properties to help marshalling structs from binary data</summary> HasReferences = true;
/// <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; }
} }
/// <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 System.Text;
using Aaru.Console; 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> /// <summary>Prints a byte array as hexadecimal values to the console</summary>
public static class PrintHex /// <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> if(array is null)
/// <param name="array">Array</param> return null;
/// <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> // TODO: Color list
/// <param name="array">Array</param> // TODO: Allow to change width
/// <param name="width">Width of line</param> string str = "Offset";
/// <param name="color">Use ANSI escape colors for sections</param> int rows = array.Length / 16;
/// <returns>String containing hexadecimal values</returns> int last = array.Length % 16;
public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false) 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) sb.AppendFormat(" {0:X2}", i);
return null; }
// TODO: Color list if(color)
// TODO: Allow to change width sb.Append("\u001b[0m");
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) sb.AppendLine();
rows++;
if(last == 0) int b = 0;
last = 16;
if(offsetLength < str.Length) string format = $"{{0:X{offsetLength}}}";
offsetLength = str.Length;
while(str.Length < offsetLength)
str += ' ';
for(int i = 0; i < rows; i++)
{
if(color) if(color)
sb.Append("\u001b[36m"); sb.Append("\u001b[36m");
sb.Append(str); sb.AppendFormat(format, b);
sb.Append(" ");
for(int i = 0; i < 16; i++)
{
sb.AppendFormat(" {0:X2}", i);
}
if(color) if(color)
sb.Append("\u001b[0m"); sb.Append("\u001b[0m");
sb.AppendLine(); sb.Append(" ");
int lastBytes = i == rows - 1 ? last : 16;
int lastSpaces = 16 - lastBytes;
int b = 0; for(int j = 0; j < lastBytes; j++)
string format = $"{{0:X{offsetLength}}}";
for(int i = 0; i < rows; i++)
{ {
if(color) sb.AppendFormat(" {0:X2}", array[b]);
sb.Append("\u001b[36m"); b++;
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();
} }
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;
using System.Text; 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> /// <summary>Converts a null-terminated (aka C string) ASCII byte array to a C# string</summary>
public static class StringHandlers /// <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> if(cString == null)
/// <returns>The corresponding C# string</returns> return null;
/// <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> int len = 0;
/// <returns>The corresponding C# string</returns>
/// <param name="cString">A null-terminated (aka C string) byte array in the specified encoding</param> for(int i = start; i < cString.Length; i++)
/// <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)
{ {
if(cString == null) if(cString[i] == 0)
return null; if(twoBytes)
{
int len = 0; if(i + 1 < cString.Length &&
cString[i + 1] == 0)
for(int i = start; i < cString.Length; i++)
{
if(cString[i] == 0)
if(twoBytes)
{ {
if(i + 1 < cString.Length && len++;
cString[i + 1] == 0)
{
len++;
break;
}
}
else
break; 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 else
unicode = 0;
if(byteIndex < dstring.Length)
unicode |= dstring[byteIndex++];
if(unicode == 0)
break; break;
temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode)); len++;
}
return temp;
} }
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; 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> /// <summary>Gets the PDP endian equivalent of the given little endian unsigned integer</summary>
public static class Swapping /// <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> x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
/// <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> return (x << 16) | (x >> 16);
/// <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> /// <summary>Swaps the endian of the specified signed integer</summary>
/// <param name="x">Unsigned short integer</param> /// <param name="x">Signed integer</param>
/// <returns>Swapped unsigned short integer</returns> /// <returns>Swapped signed integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8)); 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> return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
/// <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> /// <summary>Swaps the endian of the specified unsigned long integer</summary>
/// <param name="x">Unsigned integer</param> /// <param name="x">Unsigned long integer</param>
/// <returns>Swapped unsigned integer</returns> /// <returns>Swapped unsigned long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Swap(uint x) public static ulong Swap(ulong x)
{ {
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); 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> /// <summary>Swaps the endian of the specified signed long integer</summary>
/// <param name="x">Signed integer</param> /// <param name="x">Signed long integer</param>
/// <returns>Swapped signed integer</returns> /// <returns>Swapped signed long integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Swap(int x) public static long Swap(long x)
{ {
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); 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)); return x;
}
/// <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;
}
} }
} }