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
{
/// <summary>
/// Fills an array with the specified value
/// </summary>
/// <summary>Fills an array with the specified value</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T value)
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
ArrayFill(destinationArray, new[] {value});
}
value
});
/// <summary>
/// Fills an array with the contents of the specified array
/// </summary>
/// <summary>Fills an array with the contents of the specified array</summary>
/// <param name="destinationArray">Array</param>
/// <param name="value">Value</param>
/// <typeparam name="T">Array type</typeparam>
public static void ArrayFill<T>(T[] destinationArray, T[] value)
{
if(destinationArray == null) throw new ArgumentNullException(nameof(destinationArray));
if(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");
@@ -68,16 +64,16 @@ namespace DiscImageChef
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}
/// <summary>
/// Converts a byte array to its hexadecimal representation
/// </summary>
/// <summary>Converts a byte array to its hexadecimal representation</summary>
/// <param name="array">Byte array</param>
/// <param name="upper"><c>true</c> to use uppercase</param>
/// <returns></returns>
public static string ByteArrayToHex(byte[] array, bool upper = false)
{
StringBuilder sb = new StringBuilder();
for(long i = 0; i < array.LongLength; i++) sb.AppendFormat("{0:x2}", array[i]);
var sb = new StringBuilder();
for(long i = 0; i < array.LongLength; i++)
sb.AppendFormat("{0:x2}", array[i]);
return upper ? sb.ToString().ToUpper() : sb.ToString();
}

View File

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

View File

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

View File

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

7
CHS.cs
View File

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

View File

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

View File

@@ -34,15 +34,14 @@ namespace DiscImageChef.Helpers
{
public static class CountBits
{
/// <summary>
/// Counts the number of bits set to <c>true</c> in a number
/// </summary>
/// <summary>Counts the number of bits set to <c>true</c> in a number</summary>
/// <param name="number">Number</param>
/// <returns>Bits set to <c>true</c></returns>
public static int Count(uint number)
{
number = number - ((number >> 1) & 0x55555555);
number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
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 MacEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>
/// Day 0 of Julian Date system
/// </summary>
/// <summary>Day 0 of Julian Date system</summary>
static readonly DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
static readonly DateTime AmigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0);
/// <summary>
/// Converts a Macintosh timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a Macintosh timestamp to a .NET DateTime</summary>
/// <param name="macTimeStamp">Macintosh timestamp (seconds since 1st Jan. 1904)</param>
/// <returns>.NET DateTime</returns>
public static DateTime MacToDateTime(ulong macTimeStamp) => MacEpoch.AddTicks((long)(macTimeStamp * 10000000));
/// <summary>
/// Converts a Lisa timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a Lisa timestamp to a .NET DateTime</summary>
/// <param name="lisaTimeStamp">Lisa timestamp (seconds since 1st Jan. 1901)</param>
/// <returns>.NET DateTime</returns>
public static DateTime LisaToDateTime(uint lisaTimeStamp) => LisaEpoch.AddSeconds(lisaTimeStamp);
/// <summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(int unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixToDateTime(long unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="seconds">Seconds since 1st Jan. 1970)</param>
/// <param name="nanoseconds">Nanoseconds</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) =>
UnixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100);
/// <summary>
/// Converts a UNIX timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a UNIX timestamp to a .NET DateTime</summary>
/// <param name="unixTimeStamp">UNIX timestamp (seconds since 1st Jan. 1970)</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => UnixEpoch.AddSeconds(unixTimeStamp);
/// <summary>
/// Converts a High Sierra Format timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a High Sierra Format timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">High Sierra Format timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime HighSierraToDateTime(byte[] vdDateTime)
{
byte[] isotime = new byte[17];
Array.Copy(vdDateTime, 0, isotime, 0, 16);
return Iso9660ToDateTime(isotime);
}
// TODO: Timezone
/// <summary>
/// Converts an ISO9660 timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts an ISO9660 timestamp to a .NET DateTime</summary>
/// <param name="vdDateTime">ISO9660 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Iso9660ToDateTime(byte[] vdDateTime)
@@ -125,71 +106,89 @@ namespace DiscImageChef
fourcharvalue[1] = vdDateTime[1];
fourcharvalue[2] = vdDateTime[2];
fourcharvalue[3] = vdDateTime[3];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"",
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[1] = vdDateTime[5];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"",
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[1] = vdDateTime[7];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"",
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[1] = vdDateTime[9];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"",
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[1] = vdDateTime[11];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"",
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[1] = vdDateTime[13];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"",
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[1] = vdDateTime[15];
DicConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"",
StringHandlers.CToString(twocharvalue, Encoding.ASCII));
if(!int.TryParse(StringHandlers.CToString(twocharvalue, Encoding.ASCII), out int hundredths))
hundredths = 0;
DicConsole.DebugWriteLine("ISO9600ToDateTime handler",
"decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);",
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);
return decodedDt;
}
/// <summary>
/// Converts a VMS timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a VMS timestamp to a .NET DateTime</summary>
/// <param name="vmsDate">VMS timestamp (tenths of microseconds since day 0 of the Julian Date)</param>
/// <returns>.NET DateTime</returns>
/// <remarks>C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC</remarks>
public static DateTime VmsToDateTime(ulong vmsDate)
{
double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
return JulianEpoch.AddMilliseconds(delta);
}
/// <summary>
/// Converts an Amiga timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts an Amiga timestamp to a .NET DateTime</summary>
/// <param name="days">Days since the 1st Jan. 1978</param>
/// <param name="minutes">Minutes since o'clock</param>
/// <param name="ticks">Ticks</param>
@@ -198,12 +197,11 @@ namespace DiscImageChef
{
DateTime temp = AmigaEpoch.AddDays(days);
temp = temp.AddMinutes(minutes);
return temp.AddMilliseconds(ticks * 20);
}
/// <summary>
/// Converts an UCSD Pascal timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts an UCSD Pascal timestamp to a .NET DateTime</summary>
/// <param name="dateRecord">UCSD Pascal timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UcsdPascalToDateTime(short dateRecord)
@@ -215,12 +213,11 @@ namespace DiscImageChef
DicConsole.DebugWriteLine("UCSDPascalToDateTime handler",
"dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year,
month, day);
return new DateTime(year, month, day);
}
/// <summary>
/// Converts a DOS timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts a DOS timestamp to a .NET DateTime</summary>
/// <param name="date">Date</param>
/// <param name="time">Time</param>
/// <returns>.NET DateTime</returns>
@@ -235,20 +232,26 @@ namespace DiscImageChef
DicConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}",
date, year, month, day);
DicConsole.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); }
try
{
dosdate = new DateTime(year, month, day, hour, minute, second);
}
catch(ArgumentOutOfRangeException)
{
dosdate = new DateTime(1980, 1, 1, 0, 0, 0);
}
return dosdate;
}
/// <summary>
/// Converts a CP/M timestamp to .NET DateTime
/// </summary>
/// <summary>Converts a CP/M timestamp to .NET DateTime</summary>
/// <param name="timestamp">CP/M timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime CpmToDateTime(byte[] timestamp)
@@ -264,9 +267,7 @@ namespace DiscImageChef
return temp;
}
/// <summary>
/// Converts an ECMA timestamp to a .NET DateTime
/// </summary>
/// <summary>Converts an ECMA timestamp to a .NET DateTime</summary>
/// <param name="typeAndTimeZone">Timezone</param>
/// <param name="year">Year</param>
/// <param name="month">Month</param>
@@ -278,77 +279,79 @@ namespace DiscImageChef
/// <param name="hundredsOfMicroseconds">Hundreds of microseconds</param>
/// <param name="microseconds">Microseconds</param>
/// <returns></returns>
public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day,
byte hour,
byte minute, byte second, byte centiseconds,
byte hundredsOfMicroseconds,
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((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;
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 DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).
AddTicks(ticks).DateTime;
}
/// <summary>
/// Convers a Solaris high resolution timestamp to .NET DateTime
/// </summary>
/// <summary>Convers a Solaris high resolution timestamp to .NET DateTime</summary>
/// <param name="hrTimeStamp">Solaris high resolution timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) => UnixEpoch.AddTicks((long)(hrTimeStamp / 100));
/// <summary>
/// Converts an OS-9 timestamp to .NET DateTime
/// </summary>
/// <summary>Converts an OS-9 timestamp to .NET DateTime</summary>
/// <param name="date">OS-9 timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime Os9ToDateTime(byte[] date)
{
if(date == null || date.Length != 3 && date.Length != 5) return DateTime.MinValue;
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)
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); }
catch(ArgumentOutOfRangeException)
{
os9Date = new DateTime(1900, 0, 0, 0, 0, 0);
}
return os9Date;
}
/// <summary>
/// Converts a LIF timestamp to .NET DateTime
/// </summary>
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="date">LIF timestamp</param>
/// <returns>.NET DateTime</returns>
public static DateTime LifToDateTime(byte[] date)
{
if(date == null || date.Length != 6) return new DateTime(1970, 1, 1, 0, 0, 0);
if(date == null ||
date.Length != 6)
return new DateTime(1970, 1, 1, 0, 0, 0);
return LifToDateTime(date[0], date[1], date[2], date[3], date[4], date[5]);
}
/// <summary>
/// Converts a LIF timestamp to .NET DateTime
/// </summary>
/// <summary>Converts a LIF timestamp to .NET DateTime</summary>
/// <param name="year">Yer</param>
/// <param name="month">Month</param>
/// <param name="day">Day</param>
@@ -367,12 +370,17 @@ namespace DiscImageChef
int ihour = (hour >> 4) * 10 + (hour & 0xF);
int isecond = (second >> 4) * 10 + (second & 0xF);
if(iyear >= 70) iyear += 1900;
else iyear += 2000;
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); }
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>
public static class Marshal
{
/// <summary>
/// Returns the size of an unmanaged type in bytes.
/// </summary>
/// <summary>Returns the size of an unmanaged type in bytes.</summary>
/// <typeparam name="T">The type whose size is to be returned.</typeparam>
/// <returns>The size, in bytes, of the type that is specified by the <see cref="T" /> generic type parameter.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>()
{
return System.Runtime.InteropServices.Marshal.SizeOf<T>();
}
public static int SizeOf<T>() => System.Runtime.InteropServices.Marshal.SizeOf<T>();
/// <summary>
/// Marshal little-endian binary data to a structure
/// </summary>
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes) where T : struct
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var str =
(T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return str;
}
/// <summary>
/// Marshal little-endian binary data to a structure
/// </summary>
/// <summary>Marshal little-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
@@ -79,28 +73,28 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructureLittleEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureLittleEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>
/// Marshal big-endian binary data to a structure
/// </summary>
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T : struct
{
var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned);
object str =
(T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return(T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal big-endian binary data to a structure
/// </summary>
/// <summary>Marshal big-endian binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
@@ -110,12 +104,11 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructureBigEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructureBigEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>
/// Marshal PDP-11 binary data to a structure
/// </summary>
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
@@ -123,17 +116,18 @@ namespace DiscImageChef.Helpers
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 =
(T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T));
ptr.Free();
return(T)SwapStructureMembersEndianPdp(str);
}
}
/// <summary>
/// Marshal PDP-11 binary data to a structure
/// </summary>
/// <summary>Marshal PDP-11 binary data to a structure</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <param name="start">Start on the array where the structure begins</param>
/// <param name="length">Length of the structure in bytes</param>
@@ -143,25 +137,24 @@ namespace DiscImageChef.Helpers
public static T ByteArrayToStructurePdpEndian<T>(byte[] bytes, int start, int length) where T : struct
{
Span<byte> span = bytes;
return ByteArrayToStructurePdpEndian<T>(span.Slice(start, length).ToArray());
}
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
return MemoryMarshal.Read<T>(bytes);
}
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes) where T : struct =>
MemoryMarshal.Read<T>(bytes);
/// <summary>
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this
/// method will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
@@ -170,14 +163,11 @@ namespace DiscImageChef.Helpers
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SpanToStructureLittleEndian<T>(ReadOnlySpan<byte> bytes, int start, int length)
where T : struct
{
return MemoryMarshal.Read<T>(bytes.Slice(start, length));
}
where T : struct => MemoryMarshal.Read<T>(bytes.Slice(start, length));
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
@@ -186,12 +176,13 @@ namespace DiscImageChef.Helpers
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
var str = SpanToStructureLittleEndian<T>(bytes);
return(T)SwapStructureMembersEndian(str);
}
/// <summary>
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method will
/// crash.
/// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method
/// will crash.
/// </summary>
/// <param name="bytes">Byte span containing the binary data</param>
/// <param name="start">Start on the span where the structure begins</param>
@@ -202,6 +193,7 @@ namespace DiscImageChef.Helpers
public static T SpanToStructureBigEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
var str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return(T)SwapStructureMembersEndian(str);
}
@@ -216,6 +208,7 @@ namespace DiscImageChef.Helpers
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes);
return(T)SwapStructureMembersEndianPdp(str);
}
@@ -230,12 +223,13 @@ namespace DiscImageChef.Helpers
public static T SpanToStructurePdpEndian<T>(ReadOnlySpan<byte> bytes, int start, int length) where T : struct
{
object str = SpanToStructureLittleEndian<T>(bytes.Slice(start, length));
return(T)SwapStructureMembersEndianPdp(str);
}
/// <summary>
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the decoration
/// is not present it will marshal as a reference type containing little endian structure.
/// Marshal a structure depending on the decoration of <see cref="MarshallingPropertiesAttribute" />. If the
/// decoration is not present it will marshal as a reference type containing little endian structure.
/// </summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
@@ -248,56 +242,53 @@ namespace DiscImageChef.Helpers
public static T MarshalStructure<T>(byte[] bytes) where T : struct
{
if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute
properties)) return ByteArrayToStructureLittleEndian<T>(bytes);
properties))
return ByteArrayToStructureLittleEndian<T>(bytes);
switch(properties.Endian)
{
case BitEndian.Little:
return properties.HasReferences
? ByteArrayToStructureLittleEndian<T>(bytes)
return properties.HasReferences ? ByteArrayToStructureLittleEndian<T>(bytes)
: SpanToStructureLittleEndian<T>(bytes);
break;
case BitEndian.Big:
return properties.HasReferences
? ByteArrayToStructureBigEndian<T>(bytes)
return properties.HasReferences ? ByteArrayToStructureBigEndian<T>(bytes)
: SpanToStructureBigEndian<T>(bytes);
break;
case BitEndian.Pdp:
return properties.HasReferences
? ByteArrayToStructurePdpEndian<T>(bytes)
return properties.HasReferences ? ByteArrayToStructurePdpEndian<T>(bytes)
: SpanToStructurePdpEndian<T>(bytes);
default: throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// Swaps all members of a structure
/// </summary>
/// <summary>Swaps all members of a structure</summary>
/// <param name="str"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndian(object str)
{
var t = str.GetType();
var fieldInfo = t.GetFields();
foreach (var fi in fieldInfo)
Type t = str.GetType();
FieldInfo[] fieldInfo = t.GetFields();
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)));
}
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));
fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)));
}
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 & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8);
@@ -306,18 +297,18 @@ namespace DiscImageChef.Helpers
}
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)));
}
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);
fi.SetValue(str, (x << 16) | (x >> 16));
}
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 & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
@@ -325,21 +316,26 @@ namespace DiscImageChef.Helpers
}
else if(fi.FieldType == typeof(float))
{
var flt = (float) fi.GetValue(str);
var flt_b = BitConverter.GetBytes(flt);
fi.SetValue(str, BitConverter.ToSingle(new[] {flt_b[3], flt_b[2], flt_b[1], flt_b[0]}, 0));
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))
{
var dbl = (double) fi.GetValue(str);
var 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));
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))
else if(fi.FieldType == typeof(byte) ||
fi.FieldType == typeof(sbyte))
{
// Do nothing, can't byteswap them!
}
@@ -347,11 +343,14 @@ namespace DiscImageChef.Helpers
{
// TODO: Swap GUID
}
// 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);
var strc = SwapStructureMembersEndian(obj);
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndian(obj);
fi.SetValue(str, strc);
}
@@ -361,49 +360,58 @@ namespace DiscImageChef.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static object SwapStructureMembersEndianPdp(object str)
{
var t = str.GetType();
var fieldInfo = t.GetFields();
foreach (var 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))
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))
{
var x = (int) fi.GetValue(str);
int x = (int)fi.GetValue(str);
fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
}
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));
}
// 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);
var strc = SwapStructureMembersEndianPdp(obj);
object obj = fi.GetValue(str);
object strc = SwapStructureMembersEndianPdp(obj);
fi.SetValue(str, strc);
}
return str;
}
/// <summary>
/// Marshal a structure to little-endian binary data
/// </summary>
/// <summary>Marshal a structure to little-endian binary data</summary>
/// <param name="bytes">Byte array containing the binary data</param>
/// <typeparam name="T">Type of the structure to marshal</typeparam>
/// <returns>The binary data marshalled in a structure with the specified type</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] StructureToByteArrayLittleEndian<T>(T str) where T : struct
{
var buf = new byte[SizeOf<T>()];
var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
byte[] buf = new byte[SizeOf<T>()];
GCHandle ptr = GCHandle.Alloc(buf, GCHandleType.Pinned);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false);
ptr.Free();
return buf;
}
}

View File

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

View File

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

View File

@@ -52,6 +52,7 @@ namespace DiscImageChef
public static uint Swap(uint x)
{
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
return(x << 16) | (x >> 16);
}
@@ -59,6 +60,7 @@ namespace DiscImageChef
public static int Swap(int x)
{
x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF));
return(int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF));
}
@@ -68,6 +70,7 @@ namespace DiscImageChef
x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
return x;
}
@@ -77,6 +80,7 @@ namespace DiscImageChef
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;
}
}