diff --git a/ArrayFill.cs b/ArrayFill.cs
index a0c3687..53edd14 100644
--- a/ArrayFill.cs
+++ b/ArrayFill.cs
@@ -27,55 +27,54 @@
using System;
using System.Text;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+public static partial class ArrayHelpers
{
- public static partial class ArrayHelpers
+ /// Fills an array with the specified value
+ /// Array
+ /// Value
+ /// Array type
+ public static void ArrayFill(T[] destinationArray, T value) => ArrayFill(destinationArray, new[]
{
- /// Fills an array with the specified value
- /// Array
- /// Value
- /// Array type
- public static void ArrayFill(T[] destinationArray, T value) => ArrayFill(destinationArray, new[]
- {
- value
- });
+ value
+ });
- /// Fills an array with the contents of the specified array
- /// Array
- /// Value
- /// Array type
- public static void ArrayFill(T[] destinationArray, T[] value)
- {
- if(destinationArray == null)
- throw new ArgumentNullException(nameof(destinationArray));
+ /// Fills an array with the contents of the specified array
+ /// Array
+ /// Value
+ /// Array type
+ public static void ArrayFill(T[] destinationArray, T[] value)
+ {
+ if(destinationArray == null)
+ throw new ArgumentNullException(nameof(destinationArray));
- if(value.Length > destinationArray.Length)
- throw new ArgumentException("Length of value array must not be more than length of destination");
+ if(value.Length > destinationArray.Length)
+ throw new ArgumentException("Length of value array must not be more than length of destination");
- // set the initial array value
- Array.Copy(value, destinationArray, value.Length);
+ // set the initial array value
+ Array.Copy(value, destinationArray, value.Length);
- int arrayToFillHalfLength = destinationArray.Length / 2;
- int copyLength;
+ int arrayToFillHalfLength = destinationArray.Length / 2;
+ int copyLength;
- for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
- Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
+ for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
+ Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
- Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
- }
+ Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
+ }
- /// Converts a byte array to its hexadecimal representation
- /// Byte array
- /// true to use uppercase
- ///
- public static string ByteArrayToHex(byte[] array, bool upper = false)
- {
- var sb = new StringBuilder();
+ /// Converts a byte array to its hexadecimal representation
+ /// Byte array
+ /// true to use uppercase
+ ///
+ public static string ByteArrayToHex(byte[] array, bool upper = false)
+ {
+ var sb = new StringBuilder();
- for(long i = 0; i < array.LongLength; i++)
- sb.AppendFormat("{0:x2}", array[i]);
+ for(long i = 0; i < array.LongLength; i++)
+ sb.AppendFormat("{0:x2}", array[i]);
- return upper ? sb.ToString().ToUpper() : sb.ToString();
- }
+ return upper ? sb.ToString().ToUpper() : sb.ToString();
}
}
\ No newline at end of file
diff --git a/ArrayIsEmpty.cs b/ArrayIsEmpty.cs
index 77a6f23..93aa330 100644
--- a/ArrayIsEmpty.cs
+++ b/ArrayIsEmpty.cs
@@ -32,19 +32,18 @@
using System.Linq;
-namespace Aaru.Helpers
-{
- /// Helper operations to work with arrays
- public static partial class ArrayHelpers
- {
- /// Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)
- /// Array
- /// True if null or whitespace
- public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b == 0x00 || b == 0x20) != false;
+namespace Aaru.Helpers;
- /// Checks if an array is null or filled with the NULL byte (0x00)
- /// Array
- /// True if null
- public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false;
- }
+/// Helper operations to work with arrays
+public static partial class ArrayHelpers
+{
+ /// Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)
+ /// Array
+ /// True if null or whitespace
+ public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b == 0x00 || b == 0x20) != false;
+
+ /// Checks if an array is null or filled with the NULL byte (0x00)
+ /// Array
+ /// True if null
+ public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false;
}
\ No newline at end of file
diff --git a/BigEndianBitConverter.cs b/BigEndianBitConverter.cs
index 34e6839..03cf0ad 100644
--- a/BigEndianBitConverter.cs
+++ b/BigEndianBitConverter.cs
@@ -33,292 +33,291 @@
using System;
using System.Linq;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+///
+/// 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.
+///
+public static class BigEndianBitConverter
{
+ /// Converts the specified double-precision floating point number to a 64-bit signed integer.
+ /// The number to convert.
+ /// A 64-bit signed integer whose value is equivalent to value.
+ /// It is not currently implemented
+ public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
+
+ /// Returns the specified Boolean value as an array of bytes.
+ /// A Boolean value.
+ /// An array of bytes with length 1.
+ public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified Unicode character value as an array of bytes.
+ /// A character to convert.
+ /// An array of bytes with length 2.
+ public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified double-precision floating point value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 8.
+ public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified single-precision floating point value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 4.
+ public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 32-bit signed integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 4.
+ public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 64-bit signed integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 8.
+ public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 16-bit signed integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 2.
+ public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 32-bit unsigned integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 4.
+ public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 64-bit unsigned integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 8.
+ public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Returns the specified 16-bit unsigned integer value as an array of bytes.
+ /// The number to convert.
+ /// An array of bytes with length 2.
+ public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
+
+ /// Converts the specified 64-bit signed integer to a double-precision floating point number.
+ /// The number to convert.
+ /// A double-precision floating point number whose value is equivalent to value.
+ public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
+
+ /// Returns a Boolean value converted from one byte at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// true if the byte at in value is nonzero; otherwise, false.
+ /// value is null.
+ ///
+ /// is less than zero or greater than the
+ /// length of value minus 1.
+ ///
+ public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
+
+ /// Returns a Unicode character converted from two bytes at a specified position in a byte array.
+ /// An array.
+ /// The starting position within value.
+ /// A character formed by two bytes beginning at .
+ /// equals the length of value minus 1.
+ /// value is null.
+ ///
+ /// is less than zero or greater than the
+ /// length of value minus 1.
+ ///
+ public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
+
///
- /// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
- /// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
+ /// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
+ /// array.
///
- public static class BigEndianBitConverter
- {
- /// Converts the specified double-precision floating point number to a 64-bit signed integer.
- /// The number to convert.
- /// A 64-bit signed integer whose value is equivalent to value.
- /// It is not currently implemented
- public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A double precision floating point number formed by eight bytes beginning at .
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// is less than zero or greater than the
+ /// length of value minus 1.
+ ///
+ public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
- /// Returns the specified Boolean value as an array of bytes.
- /// A Boolean value.
- /// An array of bytes with length 1.
- public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A 16-bit signed integer formed by two bytes beginning at .
+ /// equals the length of value minus 1.
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static short ToInt16(byte[] value, int startIndex) =>
+ BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
- /// Returns the specified Unicode character value as an array of bytes.
- /// A character to convert.
- /// An array of bytes with length 2.
- public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A 32-bit signed integer formed by four bytes beginning at .
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static int ToInt32(byte[] value, int startIndex) =>
+ BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
- /// Returns the specified double-precision floating point value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 8.
- public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A 64-bit signed integer formed by eight bytes beginning at .
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// is less than zero or greater than the
+ /// length of value minus 1.
+ ///
+ public static long ToInt64(byte[] value, int startIndex) =>
+ BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
- /// Returns the specified single-precision floating point value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 4.
- public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ ///
+ /// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
+ /// array.
+ ///
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A single-precision floating point number formed by four bytes beginning at .
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// is less than zero or greater than the
+ /// length of value minus 1.
+ ///
+ public static float ToSingle(byte[] value, int startIndex) =>
+ BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
- /// Returns the specified 32-bit signed integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 4.
- public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ ///
+ /// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
+ /// representation.
+ ///
+ /// An array of bytes.
+ ///
+ /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
+ /// element in value; for example, "7F-2C-4A".
+ ///
+ /// value is null.
+ public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
- /// Returns the specified 64-bit signed integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 8.
- public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ ///
+ /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
+ /// string representation.
+ ///
+ /// An array of bytes.
+ /// The starting position within value.
+ ///
+ /// 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".
+ ///
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static string ToString(byte[] value, int startIndex) =>
+ BitConverter.ToString(value.Reverse().ToArray(), startIndex);
- /// Returns the specified 16-bit signed integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 2.
- public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ ///
+ /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
+ /// string representation.
+ ///
+ /// An array of bytes.
+ /// The starting position within value.
+ /// The number of array elements in value to convert.
+ ///
+ /// 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".
+ ///
+ /// value is null.
+ ///
+ /// startIndex or length is less than zero. -or- startIndex is greater
+ /// than zero and is greater than or equal to the length of value.
+ ///
+ ///
+ /// 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.
+ ///
+ public static string ToString(byte[] value, int startIndex, int length) =>
+ BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
- /// Returns the specified 32-bit unsigned integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 4.
- public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
+ /// The array of bytes.
+ /// The starting position within value.
+ /// A 16-bit unsigned integer formed by two bytes beginning at startIndex.
+ /// startIndex equals the length of value minus 1.
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static ushort ToUInt16(byte[] value, int startIndex) =>
+ BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
- /// Returns the specified 64-bit unsigned integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 8.
- public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A 32-bit unsigned integer formed by four bytes beginning at startIndex.
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static uint ToUInt32(byte[] value, int startIndex) =>
+ BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
- /// Returns the specified 16-bit unsigned integer value as an array of bytes.
- /// The number to convert.
- /// An array of bytes with length 2.
- public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
+ /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.
+ ///
+ /// 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.
+ ///
+ /// value is null.
+ ///
+ /// startIndex is less than zero or greater than the length of value
+ /// minus 1.
+ ///
+ public static ulong ToUInt64(byte[] value, int startIndex) =>
+ BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
- /// Converts the specified 64-bit signed integer to a double-precision floating point number.
- /// The number to convert.
- /// A double-precision floating point number whose value is equivalent to value.
- public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
-
- /// Returns a Boolean value converted from one byte at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// true if the byte at in value is nonzero; otherwise, false.
- /// value is null.
- ///
- /// is less than zero or greater than the
- /// length of value minus 1.
- ///
- public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
-
- /// Returns a Unicode character converted from two bytes at a specified position in a byte array.
- /// An array.
- /// The starting position within value.
- /// A character formed by two bytes beginning at .
- /// equals the length of value minus 1.
- /// value is null.
- ///
- /// is less than zero or greater than the
- /// length of value minus 1.
- ///
- public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
-
- ///
- /// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
- /// array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A double precision floating point number formed by eight bytes beginning at .
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// is less than zero or greater than the
- /// length of value minus 1.
- ///
- public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
-
- /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// A 16-bit signed integer formed by two bytes beginning at .
- /// equals the length of value minus 1.
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static short ToInt16(byte[] value, int startIndex) =>
- BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
-
- /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// A 32-bit signed integer formed by four bytes beginning at .
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static int ToInt32(byte[] value, int startIndex) =>
- BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
-
- /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// A 64-bit signed integer formed by eight bytes beginning at .
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// is less than zero or greater than the
- /// length of value minus 1.
- ///
- public static long ToInt64(byte[] value, int startIndex) =>
- BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
-
- ///
- /// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
- /// array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A single-precision floating point number formed by four bytes beginning at .
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// is less than zero or greater than the
- /// length of value minus 1.
- ///
- public static float ToSingle(byte[] value, int startIndex) =>
- BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
-
- ///
- /// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
- /// representation.
- ///
- /// An array of bytes.
- ///
- /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
- /// element in value; for example, "7F-2C-4A".
- ///
- /// value is null.
- public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
-
- ///
- /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
- /// string representation.
- ///
- /// An array of bytes.
- /// The starting position within value.
- ///
- /// 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".
- ///
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static string ToString(byte[] value, int startIndex) =>
- BitConverter.ToString(value.Reverse().ToArray(), startIndex);
-
- ///
- /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
- /// string representation.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// The number of array elements in value to convert.
- ///
- /// 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".
- ///
- /// value is null.
- ///
- /// startIndex or length is less than zero. -or- startIndex is greater
- /// than zero and is greater than or equal to the length of value.
- ///
- ///
- /// 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.
- ///
- public static string ToString(byte[] value, int startIndex, int length) =>
- BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
-
- /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
- /// The array of bytes.
- /// The starting position within value.
- /// A 16-bit unsigned integer formed by two bytes beginning at startIndex.
- /// startIndex equals the length of value minus 1.
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static ushort ToUInt16(byte[] value, int startIndex) =>
- BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
-
- /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// A 32-bit unsigned integer formed by four bytes beginning at startIndex.
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static uint ToUInt32(byte[] value, int startIndex) =>
- BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
-
- /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
- /// An array of bytes.
- /// The starting position within value.
- /// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.
- ///
- /// 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.
- ///
- /// value is null.
- ///
- /// startIndex is less than zero or greater than the length of value
- /// minus 1.
- ///
- public static ulong ToUInt64(byte[] value, int startIndex) =>
- BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
-
- /// Converts a big endian byte array representation of a GUID into the .NET Guid structure
- /// Byte array containing a GUID in big endian
- /// Start of the byte array to process
- /// Processed Guid
- 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]);
- }
+ /// Converts a big endian byte array representation of a GUID into the .NET Guid structure
+ /// Byte array containing a GUID in big endian
+ /// Start of the byte array to process
+ /// Processed Guid
+ 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]);
}
\ No newline at end of file
diff --git a/BitEndian.cs b/BitEndian.cs
index 857a35a..f85dccc 100644
--- a/BitEndian.cs
+++ b/BitEndian.cs
@@ -36,16 +36,15 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Describes the endianness of bits on a data structure
+public enum BitEndian
{
- /// Describes the endianness of bits on a data structure
- public enum BitEndian
- {
- /// Little-endian, or least significant bit
- Little,
- /// Big-endian, or most significant bit
- Big,
- /// PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them
- Pdp
- }
+ /// Little-endian, or least significant bit
+ Little,
+ /// Big-endian, or most significant bit
+ Big,
+ /// PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them
+ Pdp
}
\ No newline at end of file
diff --git a/CHS.cs b/CHS.cs
index b31d37d..aa58ff3 100644
--- a/CHS.cs
+++ b/CHS.cs
@@ -30,20 +30,19 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Helper operations to work with CHS values
+public static class CHS
{
- /// Helper operations to work with CHS values
- public static class CHS
- {
- /// Converts a CHS position to a LBA one
- /// Cylinder
- /// Head
- /// Sector
- /// Number of heads
- /// Number of sectors per track
- ///
- 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;
- }
+ /// Converts a CHS position to a LBA one
+ /// Cylinder
+ /// Head
+ /// Sector
+ /// Number of heads
+ /// Number of sectors per track
+ ///
+ 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;
}
\ No newline at end of file
diff --git a/CompareBytes.cs b/CompareBytes.cs
index 96dff9c..b868d4e 100644
--- a/CompareBytes.cs
+++ b/CompareBytes.cs
@@ -30,43 +30,42 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+public static partial class ArrayHelpers
{
- public static partial class ArrayHelpers
+ /// Compares two byte arrays
+ /// true if they are different in any way
+ /// true if they have the same size
+ /// Left array
+ /// Right array
+ public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1,
+ byte[] compareArray2)
{
- /// Compares two byte arrays
- /// true if they are different in any way
- /// true if they have the same size
- /// Left array
- /// Right array
- public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1,
- byte[] compareArray2)
+ different = false;
+ sameSize = true;
+
+ long leastBytes;
+
+ if(compareArray1.LongLength < compareArray2.LongLength)
{
- different = false;
- sameSize = true;
-
- long leastBytes;
-
- if(compareArray1.LongLength < compareArray2.LongLength)
- {
- sameSize = false;
- leastBytes = compareArray1.LongLength;
- }
- else if(compareArray1.LongLength > compareArray2.LongLength)
- {
- sameSize = false;
- leastBytes = compareArray2.LongLength;
- }
- else
- leastBytes = compareArray1.LongLength;
-
- for(long i = 0; i < leastBytes; i++)
- if(compareArray1[i] != compareArray2[i])
- {
- different = true;
-
- return;
- }
+ sameSize = false;
+ leastBytes = compareArray1.LongLength;
}
+ else if(compareArray1.LongLength > compareArray2.LongLength)
+ {
+ sameSize = false;
+ leastBytes = compareArray2.LongLength;
+ }
+ else
+ leastBytes = compareArray1.LongLength;
+
+ for(long i = 0; i < leastBytes; i++)
+ if(compareArray1[i] != compareArray2[i])
+ {
+ different = true;
+
+ return;
+ }
}
}
\ No newline at end of file
diff --git a/CountBits.cs b/CountBits.cs
index 88cd8d4..ba50fe7 100644
--- a/CountBits.cs
+++ b/CountBits.cs
@@ -30,20 +30,19 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
-namespace Aaru.Helpers
-{
- /// Helper operations to count bits
- public static class CountBits
- {
- /// Counts the number of bits set to true in a number
- /// Number
- /// Bits set to true
- public static int Count(uint number)
- {
- number -= (number >> 1) & 0x55555555;
- number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
+namespace Aaru.Helpers;
- return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
- }
+/// Helper operations to count bits
+public static class CountBits
+{
+ /// Counts the number of bits set to true in a number
+ /// Number
+ /// Bits set to true
+ public static int Count(uint number)
+ {
+ number -= (number >> 1) & 0x55555555;
+ number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
+
+ return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
}
}
\ No newline at end of file
diff --git a/DateHandlers.cs b/DateHandlers.cs
index c86b3d2..7fc047c 100644
--- a/DateHandlers.cs
+++ b/DateHandlers.cs
@@ -34,356 +34,355 @@ using System;
using System.Text;
using Aaru.Console;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Helper operations for timestamp management (date and time)
+public static class DateHandlers
{
- /// Helper operations for timestamp management (date and time)
- public static class DateHandlers
+ static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
+ static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
+ static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
+ /// Day 0 of Julian Date system
+ static readonly DateTime _julianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
+ static readonly DateTime _amigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
+
+ /// Converts a Macintosh timestamp to a .NET DateTime
+ /// Macintosh timestamp (seconds since 1st Jan. 1904)
+ /// .NET DateTime
+ public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000));
+
+ /// Converts a Lisa timestamp to a .NET DateTime
+ /// Lisa timestamp (seconds since 1st Jan. 1901)
+ /// .NET DateTime
+ public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp);
+
+ /// Converts a UNIX timestamp to a .NET DateTime
+ /// UNIX timestamp (seconds since 1st Jan. 1970)
+ /// .NET DateTime
+ public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+
+ /// Converts a UNIX timestamp to a .NET DateTime
+ /// UNIX timestamp (seconds since 1st Jan. 1970)
+ /// .NET DateTime
+ public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+
+ /// Converts a UNIX timestamp to a .NET DateTime
+ /// UNIX timestamp (seconds since 1st Jan. 1970)
+ /// .NET DateTime
+ public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+
+ /// Converts a UNIX timestamp to a .NET DateTime
+ /// Seconds since 1st Jan. 1970)
+ /// Nanoseconds
+ /// .NET DateTime
+ public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
+ _unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
+
+ /// Converts a UNIX timestamp to a .NET DateTime
+ /// UNIX timestamp (seconds since 1st Jan. 1970)
+ /// .NET DateTime
+ public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+
+ /// Converts a High Sierra Format timestamp to a .NET DateTime
+ /// High Sierra Format timestamp
+ /// .NET DateTime
+ public static DateTime HighSierraToDateTime(byte[] vdDateTime)
{
- static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
- static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
- static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
- /// Day 0 of Julian Date system
- static readonly DateTime _julianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
- static readonly DateTime _amigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
+ byte[] isoTime = new byte[17];
+ Array.Copy(vdDateTime, 0, isoTime, 0, 16);
- /// Converts a Macintosh timestamp to a .NET DateTime
- /// Macintosh timestamp (seconds since 1st Jan. 1904)
- /// .NET DateTime
- public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000));
+ return Iso9660ToDateTime(isoTime);
+ }
- /// Converts a Lisa timestamp to a .NET DateTime
- /// Lisa timestamp (seconds since 1st Jan. 1901)
- /// .NET DateTime
- public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp);
+ // TODO: Timezone
+ /// Converts an ISO9660 timestamp to a .NET DateTime
+ /// ISO9660 timestamp
+ /// .NET DateTime
+ public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
+ {
+ byte[] twoCharValue = new byte[2];
+ byte[] fourCharValue = new byte[4];
- /// Converts a UNIX timestamp to a .NET DateTime
- /// UNIX timestamp (seconds since 1st Jan. 1970)
- /// .NET DateTime
- public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+ fourCharValue[0] = vdDateTime[0];
+ fourCharValue[1] = vdDateTime[1];
+ fourCharValue[2] = vdDateTime[2];
+ fourCharValue[3] = vdDateTime[3];
- /// Converts a UNIX timestamp to a .NET DateTime
- /// UNIX timestamp (seconds since 1st Jan. 1970)
- /// .NET DateTime
- public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
+ StringHandlers.CToString(fourCharValue, Encoding.ASCII));
- /// Converts a UNIX timestamp to a .NET DateTime
- /// UNIX timestamp (seconds since 1st Jan. 1970)
- /// .NET DateTime
- public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+ if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year))
+ year = 0;
- /// Converts a UNIX timestamp to a .NET DateTime
- /// Seconds since 1st Jan. 1970)
- /// Nanoseconds
- /// .NET DateTime
- public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
- _unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
+ twoCharValue[0] = vdDateTime[4];
+ twoCharValue[1] = vdDateTime[5];
- /// Converts a UNIX timestamp to a .NET DateTime
- /// UNIX timestamp (seconds since 1st Jan. 1970)
- /// .NET DateTime
- public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp);
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
- /// Converts a High Sierra Format timestamp to a .NET DateTime
- /// High Sierra Format timestamp
- /// .NET DateTime
- public static DateTime HighSierraToDateTime(byte[] vdDateTime)
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month))
+ month = 0;
+
+ twoCharValue[0] = vdDateTime[6];
+ twoCharValue[1] = vdDateTime[7];
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
+
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day))
+ day = 0;
+
+ twoCharValue[0] = vdDateTime[8];
+ twoCharValue[1] = vdDateTime[9];
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
+
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour))
+ hour = 0;
+
+ twoCharValue[0] = vdDateTime[10];
+ twoCharValue[1] = vdDateTime[11];
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
+
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute))
+ minute = 0;
+
+ twoCharValue[0] = vdDateTime[12];
+ twoCharValue[1] = vdDateTime[13];
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
+
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second))
+ second = 0;
+
+ twoCharValue[0] = vdDateTime[14];
+ twoCharValue[1] = vdDateTime[15];
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
+ StringHandlers.CToString(twoCharValue, Encoding.ASCII));
+
+ if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths))
+ hundredths = 0;
+
+ AaruConsole.DebugWriteLine("ISO9600ToDateTime handler",
+ "decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
+ year, month, day, hour, minute, second, hundredths * 10);
+
+ sbyte difference = (sbyte)vdDateTime[16];
+
+ var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc);
+
+ return decodedDt.AddMinutes(difference * -15);
+ }
+
+ /// Converts a VMS timestamp to a .NET DateTime
+ /// VMS timestamp (tenths of microseconds since day 0 of the Julian Date)
+ /// .NET DateTime
+ /// C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC
+ public static DateTime VmsToDateTime(ulong vmsDate)
+ {
+ double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
+
+ return _julianEpoch.AddMilliseconds(delta);
+ }
+
+ /// Converts an Amiga timestamp to a .NET DateTime
+ /// Days since the 1st Jan. 1978
+ /// Minutes since o'clock
+ /// Ticks
+ /// .NET DateTime
+ public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks)
+ {
+ DateTime temp = _amigaEpoch.AddDays(days);
+ temp = temp.AddMinutes(minutes);
+
+ return temp.AddMilliseconds(ticks * 20);
+ }
+
+ /// Converts an UCSD Pascal timestamp to a .NET DateTime
+ /// UCSD Pascal timestamp
+ /// .NET DateTime
+ 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);
+ }
+
+ /// Converts a DOS timestamp to a .NET DateTime
+ /// Date
+ /// Time
+ /// .NET DateTime
+ public static DateTime DosToDateTime(ushort date, ushort time)
+ {
+ int year = ((date & 0xFE00) >> 9) + 1980;
+ int month = (date & 0x1E0) >> 5;
+ int day = date & 0x1F;
+ int hour = (time & 0xF800) >> 11;
+ int minute = (time & 0x7E0) >> 5;
+ int second = (time & 0x1F) * 2;
+
+ AaruConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}",
+ date, year, month, day);
+
+ AaruConsole.DebugWriteLine("DOSToDateTime handler",
+ "time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute,
+ second);
+
+ DateTime dosDate;
+
+ try
{
- byte[] isoTime = new byte[17];
- Array.Copy(vdDateTime, 0, isoTime, 0, 16);
-
- return Iso9660ToDateTime(isoTime);
+ dosDate = new DateTime(year, month, day, hour, minute, second);
+ }
+ catch(ArgumentOutOfRangeException)
+ {
+ dosDate = new DateTime(1980, 1, 1, 0, 0, 0);
}
- // TODO: Timezone
- /// Converts an ISO9660 timestamp to a .NET DateTime
- /// ISO9660 timestamp
- /// .NET DateTime
- public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
+ return dosDate;
+ }
+
+ /// Converts a CP/M timestamp to .NET DateTime
+ /// CP/M timestamp
+ /// .NET DateTime
+ 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;
+ }
+
+ /// Converts an ECMA timestamp to a .NET DateTime
+ /// Timezone
+ /// Year
+ /// Month
+ /// Day
+ /// Hour
+ /// Minute
+ /// Second
+ /// Centiseconds
+ /// Hundreds of microseconds
+ /// Microseconds
+ ///
+ 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;
+ }
+
+ /// Converts a Solaris high resolution timestamp to .NET DateTime
+ /// Solaris high resolution timestamp
+ /// .NET DateTime
+ public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) =>
+ _unixEpoch.AddTicks((long)(hrTimeStamp / 100));
+
+ /// Converts an OS-9 timestamp to .NET DateTime
+ /// OS-9 timestamp
+ /// .NET DateTime
+ public static DateTime Os9ToDateTime(byte[] date)
+ {
+ if(date == null ||
+ (date.Length != 3 && date.Length != 5))
+ return DateTime.MinValue;
+
+ DateTime os9Date;
+
+ try
{
- byte[] twoCharValue = new byte[2];
- byte[] fourCharValue = new byte[4];
-
- fourCharValue[0] = vdDateTime[0];
- fourCharValue[1] = vdDateTime[1];
- fourCharValue[2] = vdDateTime[2];
- fourCharValue[3] = vdDateTime[3];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
- StringHandlers.CToString(fourCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year))
- year = 0;
-
- twoCharValue[0] = vdDateTime[4];
- twoCharValue[1] = vdDateTime[5];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month))
- month = 0;
-
- twoCharValue[0] = vdDateTime[6];
- twoCharValue[1] = vdDateTime[7];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day))
- day = 0;
-
- twoCharValue[0] = vdDateTime[8];
- twoCharValue[1] = vdDateTime[9];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour))
- hour = 0;
-
- twoCharValue[0] = vdDateTime[10];
- twoCharValue[1] = vdDateTime[11];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute))
- minute = 0;
-
- twoCharValue[0] = vdDateTime[12];
- twoCharValue[1] = vdDateTime[13];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second))
- second = 0;
-
- twoCharValue[0] = vdDateTime[14];
- twoCharValue[1] = vdDateTime[15];
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
- StringHandlers.CToString(twoCharValue, Encoding.ASCII));
-
- if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths))
- hundredths = 0;
-
- AaruConsole.DebugWriteLine("ISO9600ToDateTime handler",
- "decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
- year, month, day, hour, minute, second, hundredths * 10);
-
- sbyte difference = (sbyte)vdDateTime[16];
-
- var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc);
-
- return decodedDt.AddMinutes(difference * -15);
+ os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0)
+ : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
+ }
+ catch(ArgumentOutOfRangeException)
+ {
+ os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
}
- /// Converts a VMS timestamp to a .NET DateTime
- /// VMS timestamp (tenths of microseconds since day 0 of the Julian Date)
- /// .NET DateTime
- /// C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC
- public static DateTime VmsToDateTime(ulong vmsDate)
+ return os9Date;
+ }
+
+ /// Converts a LIF timestamp to .NET DateTime
+ /// LIF timestamp
+ /// .NET DateTime
+ 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]);
+ }
+
+ /// Converts a LIF timestamp to .NET DateTime
+ /// Yer
+ /// Month
+ /// Day
+ /// Hour
+ /// Minute
+ /// Second
+ /// .NET DateTime
+ 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);
- }
-
- /// Converts an Amiga timestamp to a .NET DateTime
- /// Days since the 1st Jan. 1978
- /// Minutes since o'clock
- /// Ticks
- /// .NET DateTime
- public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks)
- {
- DateTime temp = _amigaEpoch.AddDays(days);
- temp = temp.AddMinutes(minutes);
-
- return temp.AddMilliseconds(ticks * 20);
- }
-
- /// Converts an UCSD Pascal timestamp to a .NET DateTime
- /// UCSD Pascal timestamp
- /// .NET DateTime
- 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);
- }
-
- /// Converts a DOS timestamp to a .NET DateTime
- /// Date
- /// Time
- /// .NET DateTime
- 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;
- }
-
- /// Converts a CP/M timestamp to .NET DateTime
- /// CP/M timestamp
- /// .NET DateTime
- 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;
- }
-
- /// Converts an ECMA timestamp to a .NET DateTime
- /// Timezone
- /// Year
- /// Month
- /// Day
- /// Hour
- /// Minute
- /// Second
- /// Centiseconds
- /// Hundreds of microseconds
- /// Microseconds
- ///
- public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour,
- byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds,
- byte microseconds)
- {
- byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12);
-
- long ticks = ((long)centiseconds * 100000) + ((long)hundredsOfMicroseconds * 1000) +
- ((long)microseconds * 10);
-
- if(specification == 0)
- return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks);
-
- ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF);
- short offset;
-
- if((preOffset & 0x800) == 0x800)
- offset = (short)(preOffset | 0xF000);
+ if(iyear >= 70)
+ iyear += 1900;
else
- offset = (short)(preOffset & 0x7FF);
+ iyear += 2000;
- if(offset == -2047)
- return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks);
-
- if(offset < -1440 ||
- offset > 1440)
- offset = 0;
-
- return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).
- AddTicks(ticks).DateTime;
+ return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
}
-
- /// Converts a Solaris high resolution timestamp to .NET DateTime
- /// Solaris high resolution timestamp
- /// .NET DateTime
- public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) =>
- _unixEpoch.AddTicks((long)(hrTimeStamp / 100));
-
- /// Converts an OS-9 timestamp to .NET DateTime
- /// OS-9 timestamp
- /// .NET DateTime
- public static DateTime Os9ToDateTime(byte[] date)
+ catch(ArgumentOutOfRangeException)
{
- if(date == null ||
- (date.Length != 3 && date.Length != 5))
- return DateTime.MinValue;
-
- DateTime os9Date;
-
- try
- {
- os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0)
- : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
- }
- catch(ArgumentOutOfRangeException)
- {
- os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
- }
-
- return os9Date;
- }
-
- /// Converts a LIF timestamp to .NET DateTime
- /// LIF timestamp
- /// .NET DateTime
- 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]);
- }
-
- /// Converts a LIF timestamp to .NET DateTime
- /// Yer
- /// Month
- /// Day
- /// Hour
- /// Minute
- /// Second
- /// .NET DateTime
- public static DateTime LifToDateTime(byte year, byte month, byte day, byte hour, byte minute, byte second)
- {
- try
- {
- int iyear = ((year >> 4) * 10) + (year & 0xF);
- int imonth = ((month >> 4) * 10) + (month & 0xF);
- int iday = ((day >> 4) * 10) + (day & 0xF);
- int iminute = ((minute >> 4) * 10) + (minute & 0xF);
- int ihour = ((hour >> 4) * 10) + (hour & 0xF);
- int isecond = ((second >> 4) * 10) + (second & 0xF);
-
- if(iyear >= 70)
- iyear += 1900;
- else
- iyear += 2000;
-
- return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
- }
- catch(ArgumentOutOfRangeException)
- {
- return new DateTime(1970, 1, 1, 0, 0, 0);
- }
+ return new DateTime(1970, 1, 1, 0, 0, 0);
}
}
}
\ No newline at end of file
diff --git a/Marshal.cs b/Marshal.cs
index d2c03e9..8a1c3bf 100644
--- a/Marshal.cs
+++ b/Marshal.cs
@@ -36,463 +36,462 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Provides methods to marshal binary data into C# structs
+public static class Marshal
{
- /// Provides methods to marshal binary data into C# structs
- public static class Marshal
+ /// Returns the size of an unmanaged type in bytes.
+ /// The type whose size is to be returned.
+ /// The size, in bytes, of the type that is specified by the generic type parameter.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int SizeOf() => System.Runtime.InteropServices.Marshal.SizeOf();
+
+ /// Marshal little-endian binary data to a structure
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructureLittleEndian(byte[] bytes) where T : struct
{
- /// Returns the size of an unmanaged type in bytes.
- /// The type whose size is to be returned.
- /// The size, in bytes, of the type that is specified by the generic type parameter.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SizeOf() => System.Runtime.InteropServices.Marshal.SizeOf();
+ var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- /// Marshal little-endian binary data to a structure
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructureLittleEndian(byte[] bytes) where T : struct
+ var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
+
+ ptr.Free();
+
+ return str;
+ }
+
+ /// Marshal little-endian binary data to a structure
+ /// Byte array containing the binary data
+ /// Start on the array where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructureLittleEndian(byte[] bytes, int start, int length) where T : struct
+ {
+ Span span = bytes;
+
+ return ByteArrayToStructureLittleEndian(span.Slice(start, length).ToArray());
+ }
+
+ /// Marshal big-endian binary data to a structure
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructureBigEndian(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);
+ }
+
+ /// Marshal big-endian binary data to a structure
+ /// Byte array containing the binary data
+ /// Start on the array where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructureBigEndian(byte[] bytes, int start, int length) where T : struct
+ {
+ Span span = bytes;
+
+ return ByteArrayToStructureBigEndian(span.Slice(start, length).ToArray());
+ }
+
+ /// Marshal PDP-11 binary data to a structure
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructurePdpEndian(byte[] bytes) where T : struct
+ {
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
+ object str =
+ (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
- return str;
- }
-
- /// Marshal little-endian binary data to a structure
- /// Byte array containing the binary data
- /// Start on the array where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructureLittleEndian(byte[] bytes, int start, int length) where T : struct
- {
- Span span = bytes;
-
- return ByteArrayToStructureLittleEndian(span.Slice(start, length).ToArray());
- }
-
- /// Marshal big-endian binary data to a structure
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructureBigEndian(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);
- }
-
- /// Marshal big-endian binary data to a structure
- /// Byte array containing the binary data
- /// Start on the array where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructureBigEndian(byte[] bytes, int start, int length) where T : struct
- {
- Span span = bytes;
-
- return ByteArrayToStructureBigEndian(span.Slice(start, length).ToArray());
- }
-
- /// Marshal PDP-11 binary data to a structure
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructurePdpEndian(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);
- }
- }
-
- /// Marshal PDP-11 binary data to a structure
- /// Byte array containing the binary data
- /// Start on the array where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T ByteArrayToStructurePdpEndian(byte[] bytes, int start, int length) where T : struct
- {
- Span span = bytes;
-
- return ByteArrayToStructurePdpEndian(span.Slice(start, length).ToArray());
- }
-
- ///
- /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
- /// method will crash.
- ///
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct =>
- MemoryMarshal.Read(bytes);
-
- ///
- /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
- /// method will crash.
- ///
- /// Byte span containing the binary data
- /// Start on the span where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructureLittleEndian(ReadOnlySpan bytes, int start, int length)
- where T : struct => MemoryMarshal.Read(bytes.Slice(start, length));
-
- ///
- /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
- /// will crash.
- ///
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructureBigEndian(ReadOnlySpan bytes) where T : struct
- {
- T str = SpanToStructureLittleEndian(bytes);
-
- return (T)SwapStructureMembersEndian(str);
- }
-
- ///
- /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
- /// will crash.
- ///
- /// Byte span containing the binary data
- /// Start on the span where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructureBigEndian(ReadOnlySpan bytes, int start, int length) where T : struct
- {
- T str = SpanToStructureLittleEndian(bytes.Slice(start, length));
-
- return (T)SwapStructureMembersEndian(str);
- }
-
- ///
- /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
- /// crash.
- ///
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructurePdpEndian(ReadOnlySpan bytes) where T : struct
- {
- object str = SpanToStructureLittleEndian(bytes);
-
return (T)SwapStructureMembersEndianPdp(str);
}
-
- ///
- /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
- /// crash.
- ///
- /// Byte array containing the binary data
- /// Start on the span where the structure begins
- /// Length of the structure in bytes
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T SpanToStructurePdpEndian(ReadOnlySpan bytes, int start, int length) where T : struct
- {
- object str = SpanToStructureLittleEndian(bytes.Slice(start, length));
-
- return (T)SwapStructureMembersEndianPdp(str);
- }
-
- ///
- /// Marshal a structure depending on the decoration of . If the
- /// decoration is not present it will marshal as a reference type containing little endian structure.
- ///
- /// Byte array containing the binary data
- /// Type of the structure to marshal
- /// The binary data marshalled in a structure with the specified type
- ///
- /// The contains an unsupported
- /// endian
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static T MarshalStructure(byte[] bytes) where T : struct
- {
- if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
- properties))
- return ByteArrayToStructureLittleEndian(bytes);
-
- switch(properties.Endian)
- {
- case BitEndian.Little:
- return properties.HasReferences ? ByteArrayToStructureLittleEndian(bytes)
- : SpanToStructureLittleEndian(bytes);
-
- case BitEndian.Big:
- return properties.HasReferences ? ByteArrayToStructureBigEndian(bytes)
- : SpanToStructureBigEndian(bytes);
-
- case BitEndian.Pdp:
- return properties.HasReferences ? ByteArrayToStructurePdpEndian(bytes)
- : SpanToStructurePdpEndian(bytes);
- default: throw new ArgumentOutOfRangeException();
- }
- }
-
- /// Swaps all members of a structure
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")]
- public static object SwapStructureMembersEndian(object str)
- {
- Type t = str.GetType();
- FieldInfo[] fieldInfo = t.GetFields();
-
- foreach(FieldInfo fi in fieldInfo)
- if(fi.FieldType == typeof(short) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)))
- {
- short x = (short)fi.GetValue(str);
- fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
- }
- else if(fi.FieldType == typeof(int) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
- {
- int x = (int)fi.GetValue(str);
- x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
- fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
- }
- else if(fi.FieldType == typeof(long) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)))
- {
- long x = (long)fi.GetValue(str);
- x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
- x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
- x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
-
- fi.SetValue(str, x);
- }
- else if(fi.FieldType == typeof(ushort) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)))
- {
- ushort x = (ushort)fi.GetValue(str);
- fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
- }
- else if(fi.FieldType == typeof(uint) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
- {
- uint x = (uint)fi.GetValue(str);
- x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
- fi.SetValue(str, (x << 16) | (x >> 16));
- }
- else if(fi.FieldType == typeof(ulong) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
- {
- ulong x = (ulong)fi.GetValue(str);
- x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
- x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
- x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
- fi.SetValue(str, x);
- }
- else if(fi.FieldType == typeof(float))
- {
- float flt = (float)fi.GetValue(str);
- byte[] flt_b = BitConverter.GetBytes(flt);
-
- fi.SetValue(str, BitConverter.ToSingle(new[]
- {
- flt_b[3], flt_b[2], flt_b[1], flt_b[0]
- }, 0));
- }
- else if(fi.FieldType == typeof(double))
- {
- double dbl = (double)fi.GetValue(str);
- byte[] dbl_b = BitConverter.GetBytes(dbl);
-
- fi.SetValue(str, BitConverter.ToDouble(new[]
- {
- dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]
- }, 0));
- }
- else if(fi.FieldType == typeof(byte) ||
- fi.FieldType == typeof(sbyte))
- {
- // Do nothing, can't byteswap them!
- }
- else if(fi.FieldType == typeof(Guid))
- {
- // TODO: Swap GUID
- }
-
- // TODO: Swap arrays
- else if(fi.FieldType.IsValueType &&
- !fi.FieldType.IsEnum &&
- !fi.FieldType.IsArray)
- {
- object obj = fi.GetValue(str);
- object strc = SwapStructureMembersEndian(obj);
- fi.SetValue(str, strc);
- }
-
- return str;
- }
-
- /// Swaps all fields in an structure considering them to follow PDP endian conventions
- /// Source structure
- /// Resulting structure
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static object SwapStructureMembersEndianPdp(object str)
- {
- Type t = str.GetType();
- FieldInfo[] fieldInfo = t.GetFields();
-
- foreach(FieldInfo fi in fieldInfo)
- if(fi.FieldType == typeof(short) ||
- fi.FieldType == typeof(long) ||
- fi.FieldType == typeof(ushort) ||
- fi.FieldType == typeof(ulong) ||
- fi.FieldType == typeof(float) ||
- fi.FieldType == typeof(double) ||
- fi.FieldType == typeof(byte) ||
- fi.FieldType == typeof(sbyte) ||
- fi.FieldType == typeof(Guid))
- {
- // Do nothing
- }
- else if(fi.FieldType == typeof(int) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
- {
- int x = (int)fi.GetValue(str);
- fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
- }
- else if(fi.FieldType == typeof(uint) ||
- (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
- {
- uint x = (uint)fi.GetValue(str);
- fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
- }
-
- // TODO: Swap arrays
- else if(fi.FieldType.IsValueType &&
- !fi.FieldType.IsEnum &&
- !fi.FieldType.IsArray)
- {
- object obj = fi.GetValue(str);
- object strc = SwapStructureMembersEndianPdp(obj);
- fi.SetValue(str, strc);
- }
-
- return str;
- }
-
- /// Marshal a structure to little-endian binary data
- /// The structure you want to marshal to binary
- /// Type of the structure to marshal
- /// The byte array representing the given structure
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static byte[] StructureToByteArrayLittleEndian(T str) where T : struct
- {
- byte[] buf = new byte[SizeOf()];
- var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
- System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
- ptr.Free();
-
- return buf;
- }
-
- /// Marshal a structure to little-endian binary data
- /// The structure you want to marshal to binary
- /// Type of the structure to marshal
- /// The byte array representing the given structure
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static byte[] StructureToByteArrayBigEndian(T str) where T : struct =>
- StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str));
-
- /// Converts a hexadecimal string into a byte array
- /// Hexadecimal string
- /// Resulting byte array
- /// Number of output bytes processed
- 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;
- }
+ }
+
+ /// Marshal PDP-11 binary data to a structure
+ /// Byte array containing the binary data
+ /// Start on the array where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ByteArrayToStructurePdpEndian(byte[] bytes, int start, int length) where T : struct
+ {
+ Span span = bytes;
+
+ return ByteArrayToStructurePdpEndian(span.Slice(start, length).ToArray());
+ }
+
+ ///
+ /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
+ /// method will crash.
+ ///
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct =>
+ MemoryMarshal.Read(bytes);
+
+ ///
+ /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
+ /// method will crash.
+ ///
+ /// Byte span containing the binary data
+ /// Start on the span where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructureLittleEndian(ReadOnlySpan bytes, int start, int length)
+ where T : struct => MemoryMarshal.Read(bytes.Slice(start, length));
+
+ ///
+ /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
+ /// will crash.
+ ///
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructureBigEndian(ReadOnlySpan bytes) where T : struct
+ {
+ T str = SpanToStructureLittleEndian(bytes);
+
+ return (T)SwapStructureMembersEndian(str);
+ }
+
+ ///
+ /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
+ /// will crash.
+ ///
+ /// Byte span containing the binary data
+ /// Start on the span where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructureBigEndian(ReadOnlySpan bytes, int start, int length) where T : struct
+ {
+ T str = SpanToStructureLittleEndian(bytes.Slice(start, length));
+
+ return (T)SwapStructureMembersEndian(str);
+ }
+
+ ///
+ /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
+ /// crash.
+ ///
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructurePdpEndian(ReadOnlySpan bytes) where T : struct
+ {
+ object str = SpanToStructureLittleEndian(bytes);
+
+ return (T)SwapStructureMembersEndianPdp(str);
+ }
+
+ ///
+ /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will
+ /// crash.
+ ///
+ /// Byte array containing the binary data
+ /// Start on the span where the structure begins
+ /// Length of the structure in bytes
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T SpanToStructurePdpEndian(ReadOnlySpan bytes, int start, int length) where T : struct
+ {
+ object str = SpanToStructureLittleEndian(bytes.Slice(start, length));
+
+ return (T)SwapStructureMembersEndianPdp(str);
+ }
+
+ ///
+ /// Marshal a structure depending on the decoration of . If the
+ /// decoration is not present it will marshal as a reference type containing little endian structure.
+ ///
+ /// Byte array containing the binary data
+ /// Type of the structure to marshal
+ /// The binary data marshalled in a structure with the specified type
+ ///
+ /// The contains an unsupported
+ /// endian
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T MarshalStructure(byte[] bytes) where T : struct
+ {
+ if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
+ properties))
+ return ByteArrayToStructureLittleEndian(bytes);
+
+ switch(properties.Endian)
+ {
+ case BitEndian.Little:
+ return properties.HasReferences ? ByteArrayToStructureLittleEndian(bytes)
+ : SpanToStructureLittleEndian(bytes);
+
+ case BitEndian.Big:
+ return properties.HasReferences ? ByteArrayToStructureBigEndian(bytes)
+ : SpanToStructureBigEndian(bytes);
+
+ case BitEndian.Pdp:
+ return properties.HasReferences ? ByteArrayToStructurePdpEndian(bytes)
+ : SpanToStructurePdpEndian(bytes);
+ default: throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ /// Swaps all members of a structure
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")]
+ public static object SwapStructureMembersEndian(object str)
+ {
+ Type t = str.GetType();
+ FieldInfo[] fieldInfo = t.GetFields();
+
+ foreach(FieldInfo fi in fieldInfo)
+ if(fi.FieldType == typeof(short) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)))
+ {
+ short x = (short)fi.GetValue(str);
+ fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
+ }
+ else if(fi.FieldType == typeof(int) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
+ {
+ int x = (int)fi.GetValue(str);
+ x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
+ fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
+ }
+ else if(fi.FieldType == typeof(long) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)))
+ {
+ long x = (long)fi.GetValue(str);
+ x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
+ x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
+ x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
+
+ fi.SetValue(str, x);
+ }
+ else if(fi.FieldType == typeof(ushort) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)))
+ {
+ ushort x = (ushort)fi.GetValue(str);
+ fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
+ }
+ else if(fi.FieldType == typeof(uint) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
+ {
+ uint x = (uint)fi.GetValue(str);
+ x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
+ fi.SetValue(str, (x << 16) | (x >> 16));
+ }
+ else if(fi.FieldType == typeof(ulong) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)))
+ {
+ ulong x = (ulong)fi.GetValue(str);
+ x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
+ x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
+ x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
+ fi.SetValue(str, x);
+ }
+ else if(fi.FieldType == typeof(float))
+ {
+ float flt = (float)fi.GetValue(str);
+ byte[] flt_b = BitConverter.GetBytes(flt);
+
+ fi.SetValue(str, BitConverter.ToSingle(new[]
+ {
+ flt_b[3], flt_b[2], flt_b[1], flt_b[0]
+ }, 0));
+ }
+ else if(fi.FieldType == typeof(double))
+ {
+ double dbl = (double)fi.GetValue(str);
+ byte[] dbl_b = BitConverter.GetBytes(dbl);
+
+ fi.SetValue(str, BitConverter.ToDouble(new[]
+ {
+ dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]
+ }, 0));
+ }
+ else if(fi.FieldType == typeof(byte) ||
+ fi.FieldType == typeof(sbyte))
+ {
+ // Do nothing, can't byteswap them!
+ }
+ else if(fi.FieldType == typeof(Guid))
+ {
+ // TODO: Swap GUID
+ }
+
+ // TODO: Swap arrays
+ else if(fi.FieldType.IsValueType &&
+ !fi.FieldType.IsEnum &&
+ !fi.FieldType.IsArray)
+ {
+ object obj = fi.GetValue(str);
+ object strc = SwapStructureMembersEndian(obj);
+ fi.SetValue(str, strc);
+ }
+
+ return str;
+ }
+
+ /// Swaps all fields in an structure considering them to follow PDP endian conventions
+ /// Source structure
+ /// Resulting structure
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static object SwapStructureMembersEndianPdp(object str)
+ {
+ Type t = str.GetType();
+ FieldInfo[] fieldInfo = t.GetFields();
+
+ foreach(FieldInfo fi in fieldInfo)
+ if(fi.FieldType == typeof(short) ||
+ fi.FieldType == typeof(long) ||
+ fi.FieldType == typeof(ushort) ||
+ fi.FieldType == typeof(ulong) ||
+ fi.FieldType == typeof(float) ||
+ fi.FieldType == typeof(double) ||
+ fi.FieldType == typeof(byte) ||
+ fi.FieldType == typeof(sbyte) ||
+ fi.FieldType == typeof(Guid))
+ {
+ // Do nothing
+ }
+ else if(fi.FieldType == typeof(int) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)))
+ {
+ int x = (int)fi.GetValue(str);
+ fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
+ }
+ else if(fi.FieldType == typeof(uint) ||
+ (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)))
+ {
+ uint x = (uint)fi.GetValue(str);
+ fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16));
+ }
+
+ // TODO: Swap arrays
+ else if(fi.FieldType.IsValueType &&
+ !fi.FieldType.IsEnum &&
+ !fi.FieldType.IsArray)
+ {
+ object obj = fi.GetValue(str);
+ object strc = SwapStructureMembersEndianPdp(obj);
+ fi.SetValue(str, strc);
+ }
+
+ return str;
+ }
+
+ /// Marshal a structure to little-endian binary data
+ /// The structure you want to marshal to binary
+ /// Type of the structure to marshal
+ /// The byte array representing the given structure
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte[] StructureToByteArrayLittleEndian(T str) where T : struct
+ {
+ byte[] buf = new byte[SizeOf()];
+ var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
+ System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
+ ptr.Free();
+
+ return buf;
+ }
+
+ /// Marshal a structure to little-endian binary data
+ /// The structure you want to marshal to binary
+ /// Type of the structure to marshal
+ /// The byte array representing the given structure
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte[] StructureToByteArrayBigEndian(T str) where T : struct =>
+ StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str));
+
+ /// Converts a hexadecimal string into a byte array
+ /// Hexadecimal string
+ /// Resulting byte array
+ /// Number of output bytes processed
+ 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;
}
}
\ No newline at end of file
diff --git a/MarshallingPropertiesAttribute.cs b/MarshallingPropertiesAttribute.cs
index 3110674..bb9f7c3 100644
--- a/MarshallingPropertiesAttribute.cs
+++ b/MarshallingPropertiesAttribute.cs
@@ -38,25 +38,24 @@
using System;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+///
+/// Defines properties to help marshalling structs from binary data
+[AttributeUsage(AttributeTargets.Struct)]
+public sealed class MarshallingPropertiesAttribute : Attribute
{
///
/// Defines properties to help marshalling structs from binary data
- [AttributeUsage(AttributeTargets.Struct)]
- public sealed class MarshallingPropertiesAttribute : Attribute
+ /// Defines properties to help marshalling structs from binary data
+ public MarshallingPropertiesAttribute(BitEndian endian)
{
- ///
- /// Defines properties to help marshalling structs from binary data
- /// Defines properties to help marshalling structs from binary data
- public MarshallingPropertiesAttribute(BitEndian endian)
- {
- Endian = endian;
- HasReferences = true;
- }
-
- /// c
- public BitEndian Endian { get; }
- /// Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc).
- public bool HasReferences { get; set; }
+ Endian = endian;
+ HasReferences = true;
}
+
+ /// c
+ public BitEndian Endian { get; }
+ /// Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc).
+ public bool HasReferences { get; set; }
}
\ No newline at end of file
diff --git a/PrintHex.cs b/PrintHex.cs
index c3ca7cd..85476c8 100644
--- a/PrintHex.cs
+++ b/PrintHex.cs
@@ -33,104 +33,103 @@
using System.Text;
using Aaru.Console;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Helper operations to get hexadecimal representations of byte arrays
+public static class PrintHex
{
- /// Helper operations to get hexadecimal representations of byte arrays
- public static class PrintHex
+ /// Prints a byte array as hexadecimal values to the console
+ /// Array
+ /// Width of line
+ public static void PrintHexArray(byte[] array, int width = 16) =>
+ AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width));
+
+ /// Prints a byte array as hexadecimal values to a string
+ /// Array
+ /// Width of line
+ /// Use ANSI escape colors for sections
+ /// String containing hexadecimal values
+ public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false)
{
- /// Prints a byte array as hexadecimal values to the console
- /// Array
- /// Width of line
- public static void PrintHexArray(byte[] array, int width = 16) =>
- AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width));
+ if(array is null)
+ return null;
- /// Prints a byte array as hexadecimal values to a string
- /// Array
- /// Width of line
- /// Use ANSI escape colors for sections
- /// String containing hexadecimal values
- public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false)
+ // TODO: Color list
+ // TODO: Allow to change width
+ string str = "Offset";
+ int rows = array.Length / 16;
+ int last = array.Length % 16;
+ int offsetLength = $"{array.Length:X}".Length;
+ var sb = new StringBuilder();
+
+ if(last > 0)
+ rows++;
+
+ if(last == 0)
+ last = 16;
+
+ if(offsetLength < str.Length)
+ offsetLength = str.Length;
+
+ while(str.Length < offsetLength)
+ str += ' ';
+
+ if(color)
+ sb.Append("\u001b[36m");
+
+ sb.Append(str);
+ sb.Append(" ");
+
+ for(int i = 0; i < 16; i++)
{
- if(array is null)
- return null;
+ sb.AppendFormat(" {0:X2}", i);
+ }
- // TODO: Color list
- // TODO: Allow to change width
- string str = "Offset";
- int rows = array.Length / 16;
- int last = array.Length % 16;
- int offsetLength = $"{array.Length:X}".Length;
- var sb = new StringBuilder();
+ if(color)
+ sb.Append("\u001b[0m");
- if(last > 0)
- rows++;
+ sb.AppendLine();
- if(last == 0)
- last = 16;
+ int b = 0;
- if(offsetLength < str.Length)
- offsetLength = str.Length;
-
- while(str.Length < offsetLength)
- str += ' ';
+ string format = $"{{0:X{offsetLength}}}";
+ for(int i = 0; i < rows; i++)
+ {
if(color)
sb.Append("\u001b[36m");
- sb.Append(str);
- sb.Append(" ");
-
- for(int i = 0; i < 16; i++)
- {
- sb.AppendFormat(" {0:X2}", i);
- }
+ sb.AppendFormat(format, b);
if(color)
sb.Append("\u001b[0m");
- sb.AppendLine();
+ sb.Append(" ");
+ int lastBytes = i == rows - 1 ? last : 16;
+ int lastSpaces = 16 - lastBytes;
- int b = 0;
-
- string format = $"{{0:X{offsetLength}}}";
-
- for(int i = 0; i < rows; i++)
+ for(int j = 0; j < lastBytes; j++)
{
- if(color)
- sb.Append("\u001b[36m");
-
- sb.AppendFormat(format, b);
-
- if(color)
- sb.Append("\u001b[0m");
-
- sb.Append(" ");
- int lastBytes = i == rows - 1 ? last : 16;
- int lastSpaces = 16 - lastBytes;
-
- for(int j = 0; j < lastBytes; j++)
- {
- sb.AppendFormat(" {0:X2}", array[b]);
- b++;
- }
-
- for(int j = 0; j < lastSpaces; j++)
- sb.Append(" ");
-
- b -= lastBytes;
- sb.Append(" ");
-
- for(int j = 0; j < lastBytes; j++)
- {
- int v = array[b];
- sb.Append((v > 31 && v < 127) || v > 159 ? (char)v : '.');
- b++;
- }
-
- sb.AppendLine();
+ sb.AppendFormat(" {0:X2}", array[b]);
+ b++;
}
- return sb.ToString();
+ for(int j = 0; j < lastSpaces; j++)
+ sb.Append(" ");
+
+ b -= lastBytes;
+ sb.Append(" ");
+
+ for(int j = 0; j < lastBytes; j++)
+ {
+ int v = array[b];
+ sb.Append((v > 31 && v < 127) || v > 159 ? (char)v : '.');
+ b++;
+ }
+
+ sb.AppendLine();
}
+
+ return sb.ToString();
}
}
\ No newline at end of file
diff --git a/StringHandlers.cs b/StringHandlers.cs
index 560c662..21a8775 100644
--- a/StringHandlers.cs
+++ b/StringHandlers.cs
@@ -33,153 +33,152 @@
using System;
using System.Text;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Helper operations to work with strings
+public static class StringHandlers
{
- /// Helper operations to work with strings
- public static class StringHandlers
+ /// Converts a null-terminated (aka C string) ASCII byte array to a C# string
+ /// The corresponding C# string
+ /// A null-terminated (aka C string) ASCII byte array
+ public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII);
+
+ /// Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string
+ /// The corresponding C# string
+ /// A null-terminated (aka C string) byte array in the specified encoding
+ /// Encoding.
+ /// Set if encoding uses 16-bit characters.
+ /// Start decoding at this position
+ public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0)
{
- /// Converts a null-terminated (aka C string) ASCII byte array to a C# string
- /// The corresponding C# string
- /// A null-terminated (aka C string) ASCII byte array
- public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII);
+ if(cString == null)
+ return null;
- /// Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string
- /// The corresponding C# string
- /// A null-terminated (aka C string) byte array in the specified encoding
- /// Encoding.
- /// Set if encoding uses 16-bit characters.
- /// Start decoding at this position
- public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0)
+ int len = 0;
+
+ for(int i = start; i < cString.Length; i++)
{
- if(cString == null)
- return null;
-
- int len = 0;
-
- for(int i = start; i < cString.Length; i++)
- {
- if(cString[i] == 0)
- if(twoBytes)
+ if(cString[i] == 0)
+ if(twoBytes)
+ {
+ if(i + 1 < cString.Length &&
+ cString[i + 1] == 0)
{
- if(i + 1 < cString.Length &&
- cString[i + 1] == 0)
- {
- len++;
+ len++;
- break;
- }
- }
- else
break;
-
- len++;
- }
-
- if(twoBytes && len % 2 > 0)
- len--;
-
- byte[] dest = new byte[len];
- Array.Copy(cString, start, dest, 0, len);
-
- return len == 0 ? "" : encoding.GetString(dest);
- }
-
- /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
- /// The corresponding C# string
- /// A length-prefixed (aka Pascal string) ASCII byte array
- public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII);
-
- /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
- /// The corresponding C# string
- /// A length-prefixed (aka Pascal string) ASCII byte array
- /// Encoding.
- /// Start decoding at this position
- 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);
- }
-
- /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
- /// The corresponding C# string
- /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array
- public static string SpacePaddedToString(byte[] spacePaddedString) =>
- SpacePaddedToString(spacePaddedString, Encoding.ASCII);
-
- /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
- /// The corresponding C# string
- /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array
- /// Encoding.
- /// Start decoding at this position
- 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);
- }
-
- /// Converts an OSTA compressed unicode byte array to a C# string
- /// The C# string.
- /// OSTA compressed unicode byte array.
- public static string DecompressUnicode(byte[] dstring)
- {
- ushort unicode;
- byte compId = dstring[0];
- string temp = "";
-
- if(compId != 8 &&
- compId != 16)
- return null;
-
- for(int byteIndex = 1; byteIndex < dstring.Length;)
- {
- if(compId == 16)
- unicode = (ushort)(dstring[byteIndex++] << 8);
+ }
+ }
else
- unicode = 0;
-
- if(byteIndex < dstring.Length)
- unicode |= dstring[byteIndex++];
-
- if(unicode == 0)
break;
- temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode));
- }
-
- return temp;
+ len++;
}
+
+ if(twoBytes && len % 2 > 0)
+ len--;
+
+ byte[] dest = new byte[len];
+ Array.Copy(cString, start, dest, 0, len);
+
+ return len == 0 ? "" : encoding.GetString(dest);
+ }
+
+ /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
+ /// The corresponding C# string
+ /// A length-prefixed (aka Pascal string) ASCII byte array
+ public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII);
+
+ /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
+ /// The corresponding C# string
+ /// A length-prefixed (aka Pascal string) ASCII byte array
+ /// Encoding.
+ /// Start decoding at this position
+ 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);
+ }
+
+ /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
+ /// The corresponding C# string
+ /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array
+ public static string SpacePaddedToString(byte[] spacePaddedString) =>
+ SpacePaddedToString(spacePaddedString, Encoding.ASCII);
+
+ /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
+ /// The corresponding C# string
+ /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array
+ /// Encoding.
+ /// Start decoding at this position
+ 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);
+ }
+
+ /// Converts an OSTA compressed unicode byte array to a C# string
+ /// The C# string.
+ /// OSTA compressed unicode byte array.
+ 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;
}
}
\ No newline at end of file
diff --git a/Swapping.cs b/Swapping.cs
index 3949872..3bc76ee 100644
--- a/Swapping.cs
+++ b/Swapping.cs
@@ -32,81 +32,80 @@
using System.Runtime.CompilerServices;
-namespace Aaru.Helpers
+namespace Aaru.Helpers;
+
+/// Helper operations to work with swapping endians
+public static class Swapping
{
- /// Helper operations to work with swapping endians
- public static class Swapping
+ /// Gets the PDP endian equivalent of the given little endian unsigned integer
+ /// Little endian unsigned integer
+ /// PDP unsigned integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint PDPFromLittleEndian(uint x) => ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
+
+ /// Gets the PDP endian equivalent of the given big endian unsigned integer
+ /// Big endian unsigned integer
+ /// PDP unsigned integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint PDPFromBigEndian(uint x) => ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
+
+ /// Swaps the endian of the specified unsigned short integer
+ /// Unsigned short integer
+ /// Swapped unsigned short integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8));
+
+ /// Swaps the endian of the specified signed short integer
+ /// Signed short integer
+ /// Swapped signed short integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static short Swap(short x) => (short)((x << 8) | ((x >> 8) & 0xFF));
+
+ /// Swaps the endian of the specified unsigned integer
+ /// Unsigned integer
+ /// Swapped unsigned integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint Swap(uint x)
{
- /// Gets the PDP endian equivalent of the given little endian unsigned integer
- /// Little endian unsigned integer
- /// PDP unsigned integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint PDPFromLittleEndian(uint x) => ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
+ x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
- /// Gets the PDP endian equivalent of the given big endian unsigned integer
- /// Big endian unsigned integer
- /// PDP unsigned integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint PDPFromBigEndian(uint x) => ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
+ return (x << 16) | (x >> 16);
+ }
- /// Swaps the endian of the specified unsigned short integer
- /// Unsigned short integer
- /// Swapped unsigned short integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8));
+ /// Swaps the endian of the specified signed integer
+ /// Signed integer
+ /// Swapped signed integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Swap(int x)
+ {
+ x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
- /// Swaps the endian of the specified signed short integer
- /// Signed short integer
- /// Swapped signed short integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static short Swap(short x) => (short)((x << 8) | ((x >> 8) & 0xFF));
+ return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
+ }
- /// Swaps the endian of the specified unsigned integer
- /// Unsigned integer
- /// Swapped unsigned integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint Swap(uint x)
- {
- x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
+ /// Swaps the endian of the specified unsigned long integer
+ /// Unsigned long integer
+ /// Swapped unsigned long integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ulong Swap(ulong x)
+ {
+ x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
+ x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
+ x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
- return (x << 16) | (x >> 16);
- }
+ return x;
+ }
- /// Swaps the endian of the specified signed integer
- /// Signed integer
- /// Swapped signed integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Swap(int x)
- {
- x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
+ /// Swaps the endian of the specified signed long integer
+ /// Signed long integer
+ /// Swapped signed long integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static long Swap(long x)
+ {
+ x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
+ x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
+ x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
- return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
- }
-
- /// Swaps the endian of the specified unsigned long integer
- /// Unsigned long integer
- /// Swapped unsigned long integer
- [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;
- }
-
- /// Swaps the endian of the specified signed long integer
- /// Signed long integer
- /// Swapped signed long integer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long Swap(long x)
- {
- x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
- x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
- x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
-
- return x;
- }
+ return x;
}
}
\ No newline at end of file