Code reformat.

This commit is contained in:
2019-11-25 00:54:39 +00:00
parent 6937468728
commit a7d7c673a1
13 changed files with 356 additions and 392 deletions

View File

@@ -31,27 +31,23 @@ namespace DiscImageChef
{ {
public static partial class ArrayHelpers public static partial class ArrayHelpers
{ {
/// <summary> /// <summary>Fills an array with the specified value</summary>
/// Fills an array with the specified value
/// </summary>
/// <param name="destinationArray">Array</param> /// <param name="destinationArray">Array</param>
/// <param name="value">Value</param> /// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam> /// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T value) public static void ArrayFill<T>(T[] destinationArray, T value) => ArrayFill(destinationArray, new[]
{ {
// if called with a single value, wrap the value in an array and call the main function value
ArrayFill(destinationArray, new[] {value}); });
}
/// <summary> /// <summary>Fills an array with the contents of the specified array</summary>
/// Fills an array with the contents of the specified array
/// </summary>
/// <param name="destinationArray">Array</param> /// <param name="destinationArray">Array</param>
/// <param name="value">Value</param> /// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam> /// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T[] value) public static void ArrayFill<T>(T[] destinationArray, T[] value)
{ {
if(destinationArray == null) throw new ArgumentNullException(nameof(destinationArray)); if(destinationArray == null)
throw new ArgumentNullException(nameof(destinationArray));
if(value.Length > destinationArray.Length) if(value.Length > destinationArray.Length)
throw new ArgumentException("Length of value array must not be more than length of destination"); throw new ArgumentException("Length of value array must not be more than length of destination");
@@ -68,16 +64,16 @@ namespace DiscImageChef
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength); Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
} }
/// <summary> /// <summary>Converts a byte array to its hexadecimal representation</summary>
/// Converts a byte array to its hexadecimal representation
/// </summary>
/// <param name="array">Byte array</param> /// <param name="array">Byte array</param>
/// <param name="upper"><c>true</c> to use uppercase</param> /// <param name="upper"><c>true</c> to use uppercase</param>
/// <returns></returns> /// <returns></returns>
public static string ByteArrayToHex(byte[] array, bool upper = false) public static string ByteArrayToHex(byte[] array, bool upper = false)
{ {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
for(long i = 0; i < array.LongLength; i++) sb.AppendFormat("{0:x2}", array[i]);
for(long i = 0; i < array.LongLength; i++)
sb.AppendFormat("{0:x2}", array[i]);
return upper ? sb.ToString().ToUpper() : sb.ToString(); return upper ? sb.ToString().ToUpper() : sb.ToString();
} }

View File

@@ -36,24 +36,15 @@ namespace DiscImageChef
{ {
public static partial class ArrayHelpers public static partial class ArrayHelpers
{ {
/// <summary> /// <summary>Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)</summary>
/// Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20)
/// </summary>
/// <param name="array">Array</param> /// <param name="array">Array</param>
/// <returns>True if null or whitespace</returns> /// <returns>True if null or whitespace</returns>
public static bool ArrayIsNullOrWhiteSpace(byte[] array) public static bool ArrayIsNullOrWhiteSpace(byte[] array) =>
{ array == null || array.All(b => b == 0x00 || b == 0x20);
return array == null || array.All(b => b == 0x00 || b == 0x20);
}
/// <summary> /// <summary>Checks if an array is null or filled with the NULL byte (0x00)</summary>
/// Checks if an array is null or filled with the NULL byte (0x00)
/// </summary>
/// <param name="array">Array</param> /// <param name="array">Array</param>
/// <returns>True if null</returns> /// <returns>True if null</returns>
public static bool ArrayIsNullOrEmpty(byte[] array) public static bool ArrayIsNullOrEmpty(byte[] array) => array == null || array.All(b => b == 0x00);
{
return array == null || array.All(b => b == 0x00);
}
} }
} }

View File

@@ -36,101 +36,73 @@ using System.Linq;
namespace DiscImageChef namespace DiscImageChef
{ {
/// <summary> /// <summary>
/// Converts base data types to an array of bytes, and an array of bytes to base /// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
/// data types. /// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
/// All info taken from the meta data of System.BitConverter. This implementation
/// allows for Endianness consideration.
/// </summary> /// </summary>
public static class BigEndianBitConverter public static class BigEndianBitConverter
{ {
/// <summary> /// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
/// Converts the specified double-precision floating point number to a 64-bit signed integer.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns> /// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
/// <exception cref="NotImplementedException">It is not currently implemented</exception> /// <exception cref="NotImplementedException">It is not currently implemented</exception>
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException(); public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
/// <summary> /// <summary>Returns the specified Boolean value as an array of bytes.</summary>
/// Returns the specified Boolean value as an array of bytes.
/// </summary>
/// <param name="value">A Boolean value.</param> /// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns> /// <returns>An array of bytes with length 1.</returns>
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
/// Returns the specified Unicode character value as an array of bytes.
/// </summary>
/// <param name="value">A character to convert.</param> /// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns> /// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
/// Returns the specified double-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns> /// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
/// Returns the specified single-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns> /// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
/// Returns the specified 32-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns> /// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
/// Returns the specified 64-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns> /// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
/// Returns the specified 16-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns> /// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns> /// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns> /// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
/// Returns the specified 16-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns> /// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray(); public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary> /// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
/// Converts the specified 64-bit signed integer to a double-precision floating point number.
/// </summary>
/// <param name="value">The number to convert.</param> /// <param name="value">The number to convert.</param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns> /// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public static double Int64BitsToDouble(long value) => throw new NotImplementedException(); public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
/// <summary> /// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
/// Returns a Boolean value converted from one byte at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns> /// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
@@ -141,9 +113,7 @@ namespace DiscImageChef
/// </exception> /// </exception>
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException(); public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary> /// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
/// Returns a Unicode character converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array.</param> /// <param name="value">An array.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns> /// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
@@ -173,9 +143,7 @@ namespace DiscImageChef
/// </exception> /// </exception>
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException(); public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary> /// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
/// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns> /// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
@@ -188,9 +156,7 @@ namespace DiscImageChef
public static short ToInt16(byte[] value, int startIndex) => public static short ToInt16(byte[] value, int startIndex) =>
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex); BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
/// <summary> /// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
/// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns> /// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
@@ -206,9 +172,7 @@ namespace DiscImageChef
public static int ToInt32(byte[] value, int startIndex) => public static int ToInt32(byte[] value, int startIndex) =>
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex); BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
/// <summary> /// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
/// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns> /// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
@@ -256,8 +220,8 @@ namespace DiscImageChef
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray()); public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
/// <summary> /// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal string /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// representation. /// string representation.
/// </summary> /// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
@@ -274,8 +238,8 @@ namespace DiscImageChef
BitConverter.ToString(value.Reverse().ToArray(), startIndex); BitConverter.ToString(value.Reverse().ToArray(), startIndex);
/// <summary> /// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal string /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// representation. /// string representation.
/// </summary> /// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
@@ -296,9 +260,7 @@ namespace DiscImageChef
public static string ToString(byte[] value, int startIndex, int length) => public static string ToString(byte[] value, int startIndex, int length) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length); BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
/// <summary> /// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
/// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">The array of bytes.</param> /// <param name="value">The array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns> /// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
@@ -311,9 +273,7 @@ namespace DiscImageChef
public static ushort ToUInt16(byte[] value, int startIndex) => public static ushort ToUInt16(byte[] value, int startIndex) =>
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex); BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
/// <summary> /// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
/// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns> /// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
@@ -329,9 +289,7 @@ namespace DiscImageChef
public static uint ToUInt32(byte[] value, int startIndex) => public static uint ToUInt32(byte[] value, int startIndex) =>
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex); BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
/// <summary> /// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
/// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param> /// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param> /// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns> /// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
@@ -347,11 +305,16 @@ namespace DiscImageChef
public static ulong ToUInt64(byte[] value, int startIndex) => public static ulong ToUInt64(byte[] value, int startIndex) =>
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex); BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
public static Guid ToGuid(byte[] value, int startIndex) => public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
new Guid(ToUInt32(value, 0 + startIndex), ToUInt16(value, 4 + startIndex), ToUInt16(value, 4 + startIndex),
ToUInt16(value, 6 + startIndex), ToUInt16(value, 6 + startIndex),
value[8 + startIndex + 0], value[8 + startIndex + 1], value[8 + startIndex + 2], value[8 + startIndex + 0],
value[8 + startIndex + 3], value[8 + startIndex + 5], value[8 + startIndex + 5], value[8 + startIndex + 1],
value[8 + startIndex + 6], value[8 + startIndex + 7]); value[8 + startIndex + 2],
value[8 + startIndex + 3],
value[8 + startIndex + 5],
value[8 + startIndex + 5],
value[8 + startIndex + 6],
value[8 + startIndex + 7]);
} }
} }

View File

@@ -42,8 +42,7 @@ namespace DiscImageChef.Helpers
public enum BitEndian public enum BitEndian
{ {
/// <summary>Little-endian, or least significant bit</summary> /// <summary>Little-endian, or least significant bit</summary>
Little, Little, /// <summary>Big-endian, or most significant bit</summary>
/// <summary>Big-endian, or most significant bit</summary>
Big, Big,
/// <summary>PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them</summary> /// <summary>PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them</summary>
Pdp Pdp

7
CHS.cs
View File

@@ -34,9 +34,7 @@ namespace DiscImageChef.Helpers
{ {
public static class CHS public static class CHS
{ {
/// <summary> /// <summary>Converts a CHS position to a LBA one</summary>
/// Converts a CHS position to a LBA one
/// </summary>
/// <param name="cyl">Cylinder</param> /// <param name="cyl">Cylinder</param>
/// <param name="head">Head</param> /// <param name="head">Head</param>
/// <param name="sector">Sector</param> /// <param name="sector">Sector</param>
@@ -44,8 +42,7 @@ namespace DiscImageChef.Helpers
/// <param name="maxSector">Number of sectors per track</param> /// <param name="maxSector">Number of sectors per track</param>
/// <returns></returns> /// <returns></returns>
public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) => public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) =>
maxHead == 0 || maxSector == 0 maxHead == 0 || maxSector == 0 ? (cyl * 16 + head) * 63 + sector - 1
? (cyl * 16 + head) * 63 + sector - 1
: (cyl * maxHead + head) * maxSector + sector - 1; : (cyl * maxHead + head) * maxSector + sector - 1;
} }
} }

View File

@@ -34,9 +34,7 @@ namespace DiscImageChef
{ {
public static partial class ArrayHelpers public static partial class ArrayHelpers
{ {
/// <summary> /// <summary>Compares two byte arrays</summary>
/// Compares two byte arrays
/// </summary>
/// <param name="different"><c>true</c> if they are different in any way</param> /// <param name="different"><c>true</c> if they are different in any way</param>
/// <param name="sameSize"><c>true</c> if they have the same size</param> /// <param name="sameSize"><c>true</c> if they have the same size</param>
/// <param name="compareArray1">Left array</param> /// <param name="compareArray1">Left array</param>
@@ -48,6 +46,7 @@ namespace DiscImageChef
sameSize = true; sameSize = true;
long leastBytes; long leastBytes;
if(compareArray1.LongLength < compareArray2.LongLength) if(compareArray1.LongLength < compareArray2.LongLength)
{ {
sameSize = false; sameSize = false;
@@ -58,12 +57,14 @@ namespace DiscImageChef
sameSize = false; sameSize = false;
leastBytes = compareArray2.LongLength; leastBytes = compareArray2.LongLength;
} }
else leastBytes = compareArray1.LongLength; else
leastBytes = compareArray1.LongLength;
for(long i = 0; i < leastBytes; i++) for(long i = 0; i < leastBytes; i++)
if(compareArray1[i] != compareArray2[i]) if(compareArray1[i] != compareArray2[i])
{ {
different = true; different = true;
return; return;
} }
} }

View File

@@ -34,16 +34,15 @@ namespace DiscImageChef.Helpers
{ {
public static class CountBits public static class CountBits
{ {
/// <summary> /// <summary>Counts the number of bits set to <c>true</c> in a number</summary>
/// Counts the number of bits set to <c>true</c> in a number
/// </summary>
/// <param name="number">Number</param> /// <param name="number">Number</param>
/// <returns>Bits set to <c>true</c></returns> /// <returns>Bits set to <c>true</c></returns>
public static int Count(uint number) public static int Count(uint number)
{ {
number = number - ((number >> 1) & 0x55555555); number = number - ((number >> 1) & 0x55555555);
number = (number & 0x33333333) + ((number >> 2) & 0x33333333); number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
return(int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
} }
} }
} }

View File

@@ -41,79 +41,60 @@ namespace DiscImageChef
static readonly DateTime LisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0); 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 MacEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0); static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary> /// <summary>Day 0 of Julian Date system</summary>
/// Day 0 of Julian Date system
/// </summary>
static readonly DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0); static readonly DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
static readonly DateTime AmigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0); static readonly DateTime AmigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
/// <summary> /// <summary>Converts a Macintosh timestamp to a .NET DateTime</summary>
/// Converts a Macintosh timestamp to a .NET DateTime
/// </summary>
/// <param name="macTimeStamp">Macintosh timestamp (seconds since 1st Jan. 1904)</param> /// <param name="macTimeStamp">Macintosh timestamp (seconds since 1st Jan. 1904)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime MacToDateTime(ulong macTimeStamp) => MacEpoch.AddTicks((long)(macTimeStamp * 10000000)); public static DateTime MacToDateTime(ulong macTimeStamp) => MacEpoch.AddTicks((long)(macTimeStamp * 10000000));
/// <summary> /// <summary>Converts a Lisa timestamp to a .NET DateTime</summary>
/// Converts a Lisa timestamp to a .NET DateTime
/// </summary>
/// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param> /// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime LisaToDateTime(uint lisaTimeStamp) => LisaEpoch.AddSeconds(lisaTimeStamp); public static DateTime LisaToDateTime(uint lisaTimeStamp) => LisaEpoch.AddSeconds(lisaTimeStamp);
/// <summary> /// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> /// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(int unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp); public static DateTime UnixToDateTime(int unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary> /// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> /// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(long unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp); public static DateTime UnixToDateTime(long unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary> /// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> /// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp); public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary> /// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <param name="seconds">Seconds since 1st Jan. 1970)</param> /// <param name="seconds">Seconds since 1st Jan. 1970)</param>
/// <param name="nanoseconds">Nanoseconds</param> /// <param name="nanoseconds">Nanoseconds</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) => public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
UnixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100); UnixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
/// <summary> /// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param> /// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp); public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary> /// <summary>Converts a High Sierra Format timestamp to a .NET DateTime</summary>
/// Converts a High Sierra Format timestamp to a .NET DateTime
/// </summary>
/// <param name="vdDateTime">High Sierra Format timestamp</param> /// <param name="vdDateTime">High Sierra Format timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime HighSierraToDateTime(byte[] vdDateTime) public static DateTime HighSierraToDateTime(byte[] vdDateTime)
{ {
byte[] isotime = new byte[17]; byte[] isotime = new byte[17];
Array.Copy(vdDateTime, 0, isotime, 0, 16); Array.Copy(vdDateTime, 0, isotime, 0, 16);
return Iso9660ToDateTime(isotime); return Iso9660ToDateTime(isotime);
} }
// TODO: Timezone // TODO: Timezone
/// <summary> /// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary>
/// Converts an ISO9660 timestamp to a .NET DateTime
/// </summary>
/// <param name="vdDateTime">ISO9660 timestamp</param> /// <param name="vdDateTime">ISO9660 timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime Iso9660ToDateTime(byte[] vdDateTime) public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
@@ -125,71 +106,89 @@ namespace DiscImageChef
fourcharvalue[1] = vdDateTime[1]; fourcharvalue[1] = vdDateTime[1];
fourcharvalue[2] = vdDateTime[2]; fourcharvalue[2] = vdDateTime[2];
fourcharvalue[3] = vdDateTime[3]; fourcharvalue[3] = vdDateTime[3];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
StringHandlers.CToString(fourcharvalue, Encoding.ASCII)); StringHandlers.CToString(fourcharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(fourcharvalue, Encoding.ASCII), out int year)) year = 0;
if(!int.TryParse(StringHandlers.CToString(fourcharvalue, Encoding.ASCII), out int year))
year = 0;
twocharvalue[0] = vdDateTime[4]; twocharvalue[0] = vdDateTime[4];
twocharvalue[1] = vdDateTime[5]; twocharvalue[1] = vdDateTime[5];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int month)) month = 0;
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int month))
month = 0;
twocharvalue[0] = vdDateTime[6]; twocharvalue[0] = vdDateTime[6];
twocharvalue[1] = vdDateTime[7]; twocharvalue[1] = vdDateTime[7];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int day)) day = 0;
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int day))
day = 0;
twocharvalue[0] = vdDateTime[8]; twocharvalue[0] = vdDateTime[8];
twocharvalue[1] = vdDateTime[9]; twocharvalue[1] = vdDateTime[9];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int hour)) hour = 0;
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int hour))
hour = 0;
twocharvalue[0] = vdDateTime[10]; twocharvalue[0] = vdDateTime[10];
twocharvalue[1] = vdDateTime[11]; twocharvalue[1] = vdDateTime[11];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int minute)) minute = 0;
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int minute))
minute = 0;
twocharvalue[0] = vdDateTime[12]; twocharvalue[0] = vdDateTime[12];
twocharvalue[1] = vdDateTime[13]; twocharvalue[1] = vdDateTime[13];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int second)) second = 0;
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int second))
second = 0;
twocharvalue[0] = vdDateTime[14]; twocharvalue[0] = vdDateTime[14];
twocharvalue[1] = vdDateTime[15]; twocharvalue[1] = vdDateTime[15];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"", DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII)); StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int hundredths)) if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int hundredths))
hundredths = 0; hundredths = 0;
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", DicConsole.DebugWriteLine("ISO9600ToDateTime handler",
"decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", "decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
year, month, day, hour, minute, second, hundredths * 10); year, month, day, hour, minute, second, hundredths * 10);
DateTime decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10,
var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10,
DateTimeKind.Unspecified); DateTimeKind.Unspecified);
return decodedDt; return decodedDt;
} }
/// <summary> /// <summary>Converts a VMS timestamp to a .NET DateTime</summary>
/// Converts a VMS timestamp to a .NET DateTime
/// </summary>
/// <param name="vmsDate">VMS timestamp (tenths of microseconds since day 0 of the Julian Date)</param> /// <param name="vmsDate">VMS timestamp (tenths of microseconds since day 0 of the Julian Date)</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
/// <remarks>C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC</remarks> /// <remarks>C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC</remarks>
public static DateTime VmsToDateTime(ulong vmsDate) public static DateTime VmsToDateTime(ulong vmsDate)
{ {
double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
return JulianEpoch.AddMilliseconds(delta); return JulianEpoch.AddMilliseconds(delta);
} }
/// <summary> /// <summary>Converts an Amiga timestamp to a .NET DateTime</summary>
/// Converts an Amiga timestamp to a .NET DateTime
/// </summary>
/// <param name="days">Days since the 1st Jan. 1978</param> /// <param name="days">Days since the 1st Jan. 1978</param>
/// <param name="minutes">Minutes since o'clock</param> /// <param name="minutes">Minutes since o'clock</param>
/// <param name="ticks">Ticks</param> /// <param name="ticks">Ticks</param>
@@ -198,12 +197,11 @@ namespace DiscImageChef
{ {
DateTime temp = AmigaEpoch.AddDays(days); DateTime temp = AmigaEpoch.AddDays(days);
temp = temp.AddMinutes(minutes); temp = temp.AddMinutes(minutes);
return temp.AddMilliseconds(ticks * 20); return temp.AddMilliseconds(ticks * 20);
} }
/// <summary> /// <summary>Converts an UCSD Pascal timestamp to a .NET DateTime</summary>
/// Converts an UCSD Pascal timestamp to a .NET DateTime
/// </summary>
/// <param name="dateRecord">UCSD Pascal timestamp</param> /// <param name="dateRecord">UCSD Pascal timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UcsdPascalToDateTime(short dateRecord) public static DateTime UcsdPascalToDateTime(short dateRecord)
@@ -215,12 +213,11 @@ namespace DiscImageChef
DicConsole.DebugWriteLine("UCSDPascalToDateTime handler", DicConsole.DebugWriteLine("UCSDPascalToDateTime handler",
"dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year, "dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year,
month, day); month, day);
return new DateTime(year, month, day); return new DateTime(year, month, day);
} }
/// <summary> /// <summary>Converts a DOS timestamp to a .NET DateTime</summary>
/// Converts a DOS timestamp to a .NET DateTime
/// </summary>
/// <param name="date">Date</param> /// <param name="date">Date</param>
/// <param name="time">Time</param> /// <param name="time">Time</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
@@ -235,20 +232,26 @@ namespace DiscImageChef
DicConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}", DicConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}",
date, year, month, day); date, year, month, day);
DicConsole.DebugWriteLine("DOSToDateTime handler", DicConsole.DebugWriteLine("DOSToDateTime handler",
"time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute, "time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute,
second); second);
DateTime dosdate; DateTime dosdate;
try { dosdate = new DateTime(year, month, day, hour, minute, second); }
catch(ArgumentOutOfRangeException) { dosdate = new DateTime(1980, 1, 1, 0, 0, 0); } try
{
dosdate = new DateTime(year, month, day, hour, minute, second);
}
catch(ArgumentOutOfRangeException)
{
dosdate = new DateTime(1980, 1, 1, 0, 0, 0);
}
return dosdate; return dosdate;
} }
/// <summary> /// <summary>Converts a CP/M timestamp to .NET DateTime</summary>
/// Converts a CP/M timestamp to .NET DateTime
/// </summary>
/// <param name="timestamp">CP/M timestamp</param> /// <param name="timestamp">CP/M timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime CpmToDateTime(byte[] timestamp) public static DateTime CpmToDateTime(byte[] timestamp)
@@ -264,9 +267,7 @@ namespace DiscImageChef
return temp; return temp;
} }
/// <summary> /// <summary>Converts an ECMA timestamp to a .NET DateTime</summary>
/// Converts an ECMA timestamp to a .NET DateTime
/// </summary>
/// <param name="typeAndTimeZone">Timezone</param> /// <param name="typeAndTimeZone">Timezone</param>
/// <param name="year">Year</param> /// <param name="year">Year</param>
/// <param name="month">Month</param> /// <param name="month">Month</param>
@@ -278,77 +279,79 @@ namespace DiscImageChef
/// <param name="hundredsOfMicroseconds">Hundreds of microseconds</param> /// <param name="hundredsOfMicroseconds">Hundreds of microseconds</param>
/// <param name="microseconds">Microseconds</param> /// <param name="microseconds">Microseconds</param>
/// <returns></returns> /// <returns></returns>
public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour,
byte hour, byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds,
byte minute, byte second, byte centiseconds,
byte hundredsOfMicroseconds,
byte microseconds) byte microseconds)
{ {
byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12); byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12);
long ticks = (long)centiseconds * 100000 + (long)hundredsOfMicroseconds * 1000 + long ticks = (long)centiseconds * 100000 + (long)hundredsOfMicroseconds * 1000 +
(long)microseconds * 10; (long)microseconds * 10;
if(specification == 0) if(specification == 0)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks); return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks);
ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF); ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF);
short offset; short offset;
if((preOffset & 0x800) == 0x800) offset = (short)(preOffset | 0xF000); if((preOffset & 0x800) == 0x800)
else offset = (short)(preOffset & 0x7FF); offset = (short)(preOffset | 0xF000);
else
offset = (short)(preOffset & 0x7FF);
if(offset == -2047) if(offset == -2047)
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks); return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks);
if(offset < -1440 || offset > 1440) offset = 0; if(offset < -1440 ||
offset > 1440)
offset = 0;
return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)) return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).
.AddTicks(ticks).DateTime; AddTicks(ticks).DateTime;
} }
/// <summary> /// <summary>Convers a Solaris high resolution timestamp to .NET DateTime</summary>
/// Convers a Solaris high resolution timestamp to .NET DateTime
/// </summary>
/// <param name="hrTimeStamp">Solaris high resolution timestamp</param> /// <param name="hrTimeStamp">Solaris high resolution timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) => UnixEpoch.AddTicks((long)(hrTimeStamp / 100)); public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) => UnixEpoch.AddTicks((long)(hrTimeStamp / 100));
/// <summary> /// <summary>Converts an OS-9 timestamp to .NET DateTime</summary>
/// Converts an OS-9 timestamp to .NET DateTime
/// </summary>
/// <param name="date">OS-9 timestamp</param> /// <param name="date">OS-9 timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime Os9ToDateTime(byte[] date) public static DateTime Os9ToDateTime(byte[] date)
{ {
if(date == null || date.Length != 3 && date.Length != 5) return DateTime.MinValue; if(date == null ||
date.Length != 3 && date.Length != 5)
return DateTime.MinValue;
DateTime os9Date; DateTime os9Date;
try try
{ {
os9Date = date.Length == 5 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], date[3], date[4], 0)
: new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0); : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0);
} }
catch(ArgumentOutOfRangeException) { os9Date = new DateTime(1900, 0, 0, 0, 0, 0); } catch(ArgumentOutOfRangeException)
{
os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
}
return os9Date; return os9Date;
} }
/// <summary> /// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// Converts a LIF timestamp to .NET DateTime
/// </summary>
/// <param name="date">LIF timestamp</param> /// <param name="date">LIF timestamp</param>
/// <returns>.NET DateTime</returns> /// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte[] date) public static DateTime LifToDateTime(byte[] date)
{ {
if(date == null || date.Length != 6) return new DateTime(1970, 1, 1, 0, 0, 0); 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]); return LifToDateTime(date[0], date[1], date[2], date[3], date[4], date[5]);
} }
/// <summary> /// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// Converts a LIF timestamp to .NET DateTime
/// </summary>
/// <param name="year">Yer</param> /// <param name="year">Yer</param>
/// <param name="month">Month</param> /// <param name="month">Month</param>
/// <param name="day">Day</param> /// <param name="day">Day</param>
@@ -367,12 +370,17 @@ namespace DiscImageChef
int ihour = (hour >> 4) * 10 + (hour & 0xF); int ihour = (hour >> 4) * 10 + (hour & 0xF);
int isecond = (second >> 4) * 10 + (second & 0xF); int isecond = (second >> 4) * 10 + (second & 0xF);
if(iyear >= 70) iyear += 1900; if(iyear >= 70)
else iyear += 2000; iyear += 1900;
else
iyear += 2000;
return new DateTime(iyear, imonth, iday, ihour, iminute, isecond); return new DateTime(iyear, imonth, iday, ihour, iminute, isecond);
} }
catch(ArgumentOutOfRangeException) { return new DateTime(1970, 1, 1, 0, 0, 0); } catch(ArgumentOutOfRangeException)
{
return new DateTime(1970, 1, 1, 0, 0, 0);
}
} }
} }
} }

View File

@@ -40,36 +40,30 @@ namespace DiscImageChef.Helpers
/// <summary>Provides methods to marshal binary data into C# structs</summary> /// <summary>Provides methods to marshal binary data into C# structs</summary>
public static class Marshal public static class Marshal
{ {
/// <summary> /// <summary>Returns the size of an unmanaged type in bytes.</summary>
/// Returns the size of an unmanaged type in bytes.
/// </summary>
/// <typeparam name="T">The type whose size is to be returned.</typeparam> /// <typeparam name="T">The type whose size is to be returned.</typeparam>
/// <returns>The size, in bytes, of the type that is specified by the <see cref="T" /> generic type parameter.</returns> /// <returns>The size, in bytes, of the type that is specified by the <see cref="T" /> generic type parameter.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>() public static int SizeOf<T>() => System.Runtime.InteropServices.Marshal.SizeOf<T>();
{
return System.Runtime.InteropServices.Marshal.SizeOf<T>();
}
/// <summary> /// <summary>Marshal little-endian binary data to a structure</summary>
/// Marshal little-endian binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct
{ {
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var str = var str =
(T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free(); ptr.Free();
return str; return str;
} }
/// <summary> /// <summary>Marshal little-endian binary data to a structure</summary>
/// Marshal little-endian binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param> /// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param> /// <param name="length">Length of the structure in bytes</param>
@@ -79,28 +73,28 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes, int start, int length) where T : struct public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes, int start, int length) where T : struct
{ {
Span<byte> span = bytes; Span<byte> span = bytes;
return ByteArrayToStructureLittleEndian<T>(span.Slice(start, length).ToArray()); return ByteArrayToStructureLittleEndian<T>(span.Slice(start, length).ToArray());
} }
/// <summary> /// <summary>Marshal big-endian binary data to a structure</summary>
/// Marshal big-endian binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T : struct public static T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T : struct
{ {
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str = object str =
(T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free(); ptr.Free();
return (T) SwapStructureMembersEndian(str);
return(T)SwapStructureMembersEndian(str);
} }
/// <summary> /// <summary>Marshal big-endian binary data to a structure</summary>
/// Marshal big-endian binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param> /// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param> /// <param name="length">Length of the structure in bytes</param>
@@ -110,12 +104,11 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes, int start, int length) where T : struct public static T ByteArrayToStructureBigEndian<T>(byte[] bytes, int start, int length) where T : struct
{ {
Span<byte> span = bytes; Span<byte> span = bytes;
return ByteArrayToStructureBigEndian<T>(span.Slice(start, length).ToArray()); return ByteArrayToStructureBigEndian<T>(span.Slice(start, length).ToArray());
} }
/// <summary> /// <summary>Marshal PDP-11 binary data to a structure</summary>
/// Marshal PDP-11 binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
@@ -123,17 +116,18 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes) where T : struct public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes) where T : struct
{ {
{ {
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str = object str =
(T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free(); ptr.Free();
return (T) SwapStructureMembersEndianPdp(str);
return(T)SwapStructureMembersEndianPdp(str);
} }
} }
/// <summary> /// <summary>Marshal PDP-11 binary data to a structure</summary>
/// Marshal PDP-11 binary data to a structure
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param> /// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param> /// <param name="length">Length of the structure in bytes</param>
@@ -143,25 +137,24 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct
{ {
Span<byte> span = bytes; Span<byte> span = bytes;
return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray()); return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray());
} }
/// <summary> /// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this method /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// will crash. /// method will crash.
/// </summary> /// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct =>
{ MemoryMarshal.Read<T>(bytes);
return MemoryMarshal.Read<T>(bytes);
}
/// <summary> /// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this method /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// will crash. /// method will crash.
/// </summary> /// </summary>
/// <param name="bytes">Byte span containing the binary data</param> /// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param> /// <param name="start">Start on the span where the structure begins</param>
@@ -170,14 +163,11 @@ namespace DiscImageChef.Helpers
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length)
where T : struct where T : struct => MemoryMarshal.Read<T>(bytes.Slice(start, length));
{
return MemoryMarshal.Read<T>(bytes.Slice(start, length));
}
/// <summary> /// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method will /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// crash. /// will crash.
/// </summary> /// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
@@ -186,12 +176,13 @@ namespace DiscImageChef.Helpers
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{ {
var str = SpanToStructureLittleEndian<T>(bytes); var str = SpanToStructureLittleEndian<T>(bytes);
return (T) SwapStructureMembersEndian(str);
return(T)SwapStructureMembersEndian(str);
} }
/// <summary> /// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method will /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// crash. /// will crash.
/// </summary> /// </summary>
/// <param name="bytes">Byte span containing the binary data</param> /// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param> /// <param name="start">Start on the span where the structure begins</param>
@@ -202,7 +193,8 @@ namespace DiscImageChef.Helpers
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{ {
var str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length)); var str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T) SwapStructureMembersEndian(str);
return(T)SwapStructureMembersEndian(str);
} }
/// <summary> /// <summary>
@@ -216,7 +208,8 @@ namespace DiscImageChef.Helpers
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{ {
object str = SpanToStructureLittleEndian<T>(bytes); object str = SpanToStructureLittleEndian<T>(bytes);
return (T) SwapStructureMembersEndianPdp(str);
return(T)SwapStructureMembersEndianPdp(str);
} }
/// <summary> /// <summary>
@@ -230,12 +223,13 @@ namespace DiscImageChef.Helpers
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{ {
object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length)); object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return (T) SwapStructureMembersEndianPdp(str);
return(T)SwapStructureMembersEndianPdp(str);
} }
/// <summary> /// <summary>
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the decoration /// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the
/// is not present it will marshal as a reference type containing little endian structure. /// decoration is not present it will marshal as a reference type containing little endian structure.
/// </summary> /// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
@@ -247,111 +241,116 @@ namespace DiscImageChef.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T MarshalStructure<T>(byte[] bytes) where T : struct public static T MarshalStructure<T>(byte[] bytes) where T : struct
{ {
if (!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
properties)) return ByteArrayToStructureLittleEndian<T>(bytes); properties))
return ByteArrayToStructureLittleEndian<T>(bytes);
switch (properties.Endian) switch(properties.Endian)
{ {
case BitEndian.Little: case BitEndian.Little:
return properties.HasReferences return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
? ByteArrayToStructureLittleEndian<T>(bytes)
: SpanToStructureLittleEndian<T>(bytes); : SpanToStructureLittleEndian<T>(bytes);
break; break;
case BitEndian.Big: case BitEndian.Big:
return properties.HasReferences return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes)
? ByteArrayToStructureBigEndian<T>(bytes)
: SpanToStructureBigEndian<T>(bytes); : SpanToStructureBigEndian<T>(bytes);
break; break;
case BitEndian.Pdp: case BitEndian.Pdp:
return properties.HasReferences return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes)
? ByteArrayToStructurePdpEndian<T>(bytes)
: SpanToStructurePdpEndian<T>(bytes); : SpanToStructurePdpEndian<T>(bytes);
default: throw new ArgumentOutOfRangeException(); default: throw new ArgumentOutOfRangeException();
} }
} }
/// <summary> /// <summary>Swaps all members of a structure</summary>
/// Swaps all members of a structure
/// </summary>
/// <param name="str"></param> /// <param name="str"></param>
/// <returns></returns> /// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndian(object str) public static object SwapStructureMembersEndian(object str)
{ {
var t = str.GetType(); Type t = str.GetType();
var fieldInfo = t.GetFields(); FieldInfo[] fieldInfo = t.GetFields();
foreach (var fi in fieldInfo)
if (fi.FieldType == typeof(short)) foreach(FieldInfo fi in fieldInfo)
if(fi.FieldType == typeof(short))
{ {
var x = (short) fi.GetValue(str); short x = (short)fi.GetValue(str);
fi.SetValue(str, (short) ((x << 8) | ((x >> 8) & 0xFF))); fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF)));
} }
else if (fi.FieldType == typeof(int)) else if(fi.FieldType == typeof(int))
{ {
var x = (int) fi.GetValue(str); int x = (int)fi.GetValue(str);
x = (int) (((x << 8) & 0xFF00FF00) | (((uint) x >> 8) & 0xFF00FF)); x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
fi.SetValue(str, (int) (((uint) x << 16) | (((uint) x >> 16) & 0xFFFF))); fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
} }
else if (fi.FieldType == typeof(long)) else if(fi.FieldType == typeof(long))
{ {
var x = (long) fi.GetValue(str); long x = (long)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | (long) (((ulong) x & 0xFFFFFFFF00000000) >> 32); x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long) (((ulong) x & 0xFFFF0000FFFF0000) >> 16); x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long) (((ulong) x & 0xFF00FF00FF00FF00) >> 8); x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x); fi.SetValue(str, x);
} }
else if (fi.FieldType == typeof(ushort)) else if(fi.FieldType == typeof(ushort))
{ {
var x = (ushort) fi.GetValue(str); ushort x = (ushort)fi.GetValue(str);
fi.SetValue(str, (ushort) ((x << 8) | (x >> 8))); fi.SetValue(str, (ushort)((x << 8) | (x >> 8)));
} }
else if (fi.FieldType == typeof(uint)) else if(fi.FieldType == typeof(uint))
{ {
var x = (uint) fi.GetValue(str); uint x = (uint)fi.GetValue(str);
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
fi.SetValue(str, (x << 16) | (x >> 16)); fi.SetValue(str, (x << 16) | (x >> 16));
} }
else if (fi.FieldType == typeof(ulong)) else if(fi.FieldType == typeof(ulong))
{ {
var x = (ulong) fi.GetValue(str); ulong x = (ulong)fi.GetValue(str);
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32); x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
fi.SetValue(str, x); fi.SetValue(str, x);
} }
else if (fi.FieldType == typeof(float)) else if(fi.FieldType == typeof(float))
{ {
var flt = (float) fi.GetValue(str); float flt = (float)fi.GetValue(str);
var flt_b = BitConverter.GetBytes(flt); 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));
} fi.SetValue(str, BitConverter.ToSingle(new[]
else if (fi.FieldType == typeof(double))
{ {
var dbl = (double) fi.GetValue(str); flt_b[3], flt_b[2], flt_b[1], flt_b[0]
var dbl_b = BitConverter.GetBytes(dbl); }, 0));
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)) 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! // Do nothing, can't byteswap them!
} }
else if (fi.FieldType == typeof(Guid)) else if(fi.FieldType == typeof(Guid))
{ {
// TODO: Swap GUID // TODO: Swap GUID
} }
// TODO: Swap arrays and enums // TODO: Swap arrays and enums
else if (fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{ {
var obj = fi.GetValue(str); object obj = fi.GetValue(str);
var strc = SwapStructureMembersEndian(obj); object strc = SwapStructureMembersEndian(obj);
fi.SetValue(str, strc); fi.SetValue(str, strc);
} }
@@ -361,49 +360,58 @@ namespace DiscImageChef.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndianPdp(object str) public static object SwapStructureMembersEndianPdp(object str)
{ {
var t = str.GetType(); Type t = str.GetType();
var fieldInfo = t.GetFields(); FieldInfo[] fieldInfo = t.GetFields();
foreach (var fi in fieldInfo)
if (fi.FieldType == typeof(short) || fi.FieldType == typeof(long) || fi.FieldType == typeof(ushort) || foreach(FieldInfo fi in fieldInfo)
fi.FieldType == typeof(ulong) || fi.FieldType == typeof(float) || fi.FieldType == typeof(double) || if(fi.FieldType == typeof(short) ||
fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte) || fi.FieldType == typeof(Guid)) 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 // Do nothing
} }
else if (fi.FieldType == typeof(int)) else if(fi.FieldType == typeof(int))
{ {
var x = (int) fi.GetValue(str); int x = (int)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16)); fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
} }
else if (fi.FieldType == typeof(uint)) else if(fi.FieldType == typeof(uint))
{ {
var x = (uint) fi.GetValue(str); uint x = (uint)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16)); fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
} }
// TODO: Swap arrays and enums // TODO: Swap arrays and enums
else if (fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) else if(fi.FieldType.IsValueType &&
!fi.FieldType.IsEnum &&
!fi.FieldType.IsArray)
{ {
var obj = fi.GetValue(str); object obj = fi.GetValue(str);
var strc = SwapStructureMembersEndianPdp(obj); object strc = SwapStructureMembersEndianPdp(obj);
fi.SetValue(str, strc); fi.SetValue(str, strc);
} }
return str; return str;
} }
/// <summary> /// <summary>Marshal a structure to little-endian binary data</summary>
/// Marshal a structure to little-endian binary data
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param> /// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam> /// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns> /// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct
{ {
var buf = new byte[SizeOf<T>()]; byte[] buf = new byte[SizeOf<T>()];
var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned); GCHandle ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false); System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
ptr.Free(); ptr.Free();
return buf; return buf;
} }
} }

View File

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

View File

@@ -37,16 +37,12 @@ namespace DiscImageChef
{ {
public static class StringHandlers public static class StringHandlers
{ {
/// <summary> /// <summary>Converts a null-terminated (aka C string) ASCII byte array to a C# string</summary>
/// Converts a null-terminated (aka C string) ASCII byte array to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="CString">A null-terminated (aka C string) ASCII byte array</param> /// <param name="CString">A null-terminated (aka C string) ASCII byte array</param>
public static string CToString(byte[] CString) => CToString(CString, Encoding.ASCII); public static string CToString(byte[] CString) => CToString(CString, Encoding.ASCII);
/// <summary> /// <summary>Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string</summary>
/// Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="CString">A null-terminated (aka C string) byte array in the specified encoding</param> /// <param name="CString">A null-terminated (aka C string) byte array in the specified encoding</param>
/// <param name="encoding">Encoding.</param> /// <param name="encoding">Encoding.</param>
@@ -54,7 +50,8 @@ namespace DiscImageChef
/// <param name="start">Start decodint at this position</param> /// <param name="start">Start decodint at this position</param>
public static string CToString(byte[] CString, Encoding encoding, bool twoBytes = false, int start = 0) public static string CToString(byte[] CString, Encoding encoding, bool twoBytes = false, int start = 0)
{ {
if(CString == null) return null; if(CString == null)
return null;
int len = 0; int len = 0;
@@ -63,9 +60,11 @@ namespace DiscImageChef
if(CString[i] == 0) if(CString[i] == 0)
if(twoBytes) if(twoBytes)
{ {
if(i + 1 < CString.Length && CString[i + 1] == 0) if(i + 1 < CString.Length &&
CString[i + 1] == 0)
{ {
len++; len++;
break; break;
} }
} }
@@ -75,7 +74,8 @@ namespace DiscImageChef
len++; len++;
} }
if(twoBytes && len % 2 > 0) len--; if(twoBytes && len % 2 > 0)
len--;
byte[] dest = new byte[len]; byte[] dest = new byte[len];
Array.Copy(CString, start, dest, 0, len); Array.Copy(CString, start, dest, 0, len);
@@ -83,30 +83,28 @@ namespace DiscImageChef
return len == 0 ? "" : encoding.GetString(dest); return len == 0 ? "" : encoding.GetString(dest);
} }
/// <summary> /// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="PascalString">A length-prefixed (aka Pascal string) ASCII byte array</param> /// <param name="PascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
public static string PascalToString(byte[] PascalString) => PascalToString(PascalString, Encoding.ASCII); public static string PascalToString(byte[] PascalString) => PascalToString(PascalString, Encoding.ASCII);
/// <summary> /// <summary>Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string</summary>
/// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="PascalString">A length-prefixed (aka Pascal string) ASCII byte array</param> /// <param name="PascalString">A length-prefixed (aka Pascal string) ASCII byte array</param>
/// <param name="encoding">Encoding.</param> /// <param name="encoding">Encoding.</param>
/// <param name="start">Start decodint at this position</param> /// <param name="start">Start decodint at this position</param>
public static string PascalToString(byte[] PascalString, Encoding encoding, int start = 0) public static string PascalToString(byte[] PascalString, Encoding encoding, int start = 0)
{ {
if(PascalString == null) return null; if(PascalString == null)
return null;
byte length = PascalString[start]; byte length = PascalString[start];
int len = 0; int len = 0;
for(int i = start + 1; i < length + 1 && i < PascalString.Length; i++) for(int i = start + 1; i < length + 1 && i < PascalString.Length; i++)
{ {
if(PascalString[i] == 0) break; if(PascalString[i] == 0)
break;
len++; len++;
} }
@@ -117,43 +115,41 @@ namespace DiscImageChef
return len == 0 ? "" : encoding.GetString(dest); return len == 0 ? "" : encoding.GetString(dest);
} }
/// <summary> /// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="SpacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param> /// <param name="SpacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
public static string SpacePaddedToString(byte[] SpacePaddedString) => public static string SpacePaddedToString(byte[] SpacePaddedString) =>
SpacePaddedToString(SpacePaddedString, Encoding.ASCII); SpacePaddedToString(SpacePaddedString, Encoding.ASCII);
/// <summary> /// <summary>Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string</summary>
/// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string
/// </summary>
/// <returns>The corresponding C# string</returns> /// <returns>The corresponding C# string</returns>
/// <param name="SpacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param> /// <param name="SpacePaddedString">A space (' ', 0x20, ASCII SPACE) padded ASCII byte array</param>
/// <param name="encoding">Encoding.</param> /// <param name="encoding">Encoding.</param>
/// <param name="start">Start decodint at this position</param> /// <param name="start">Start decodint at this position</param>
public static string SpacePaddedToString(byte[] SpacePaddedString, Encoding encoding, int start = 0) public static string SpacePaddedToString(byte[] SpacePaddedString, Encoding encoding, int start = 0)
{ {
if(SpacePaddedString == null) return null; if(SpacePaddedString == null)
return null;
int len = start; int len = start;
for(int i = SpacePaddedString.Length; i >= start; i--) for(int i = SpacePaddedString.Length; i >= start; i--)
{ {
if(i == start) return ""; if(i == start)
return"";
if(SpacePaddedString[i - 1] == 0x20) continue; if(SpacePaddedString[i - 1] == 0x20)
continue;
len = i; len = i;
break; break;
} }
return len == 0 ? "" : encoding.GetString(SpacePaddedString, start, len); return len == 0 ? "" : encoding.GetString(SpacePaddedString, start, len);
} }
/// <summary> /// <summary>Converts an OSTA compressed unicode byte array to a C# string</summary>
/// Converts an OSTA compressed unicode byte array to a C# string
/// </summary>
/// <returns>The C# string.</returns> /// <returns>The C# string.</returns>
/// <param name="dstring">OSTA compressed unicode byte array.</param> /// <param name="dstring">OSTA compressed unicode byte array.</param>
public static string DecompressUnicode(byte[] dstring) public static string DecompressUnicode(byte[] dstring)
@@ -162,16 +158,22 @@ namespace DiscImageChef
byte compId = dstring[0]; byte compId = dstring[0];
string temp = ""; string temp = "";
if(compId != 8 && compId != 16) return null; if(compId != 8 &&
compId != 16)
return null;
for(int byteIndex = 1; byteIndex < dstring.Length;) for(int byteIndex = 1; byteIndex < dstring.Length;)
{ {
if(compId == 16) unicode = (ushort)(dstring[byteIndex++] << 8); if(compId == 16)
else unicode = 0; unicode = (ushort)(dstring[byteIndex++] << 8);
else
unicode = 0;
if(byteIndex < dstring.Length) unicode |= dstring[byteIndex++]; if(byteIndex < dstring.Length)
unicode |= dstring[byteIndex++];
if(unicode == 0) break; if(unicode == 0)
break;
temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode)); temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode));
} }

View File

@@ -52,14 +52,16 @@ namespace DiscImageChef
public static uint Swap(uint x) public static uint Swap(uint x)
{ {
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
return (x << 16) | (x >> 16);
return(x << 16) | (x >> 16);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Swap(int x) public static int Swap(int x)
{ {
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
return(int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -68,6 +70,7 @@ namespace DiscImageChef
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32); x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
return x; return x;
} }
@@ -77,6 +80,7 @@ namespace DiscImageChef
x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
return x; return x;
} }
} }