[Skippers/] Much needed whitespace and doc cleanup

This commit is contained in:
Matt Nadareski
2019-02-08 21:01:54 -08:00
parent e5e6317f2a
commit 7c79d3ea45
2 changed files with 722 additions and 654 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -17,196 +17,245 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.Skippers namespace SabreTools.Library.Skippers
{ {
public class SkipperRule public class SkipperRule
{ {
// Public variables #region Fields
public long? StartOffset; // null is EOF
public long? EndOffset; // null if EOF
public HeaderSkipOperation Operation;
public List<SkipperTest> Tests;
public string SourceFile;
/// <summary> /// <summary>
/// Transform an input file using the given rule /// Starting offset for applying rule
/// </summary> /// </summary>
/// <param name="input">Input file name</param> public long? StartOffset { get; set; } // null is EOF
/// <param name="output">Output file name</param>
/// <returns>True if the file was transformed properly, false otherwise</returns>
public bool TransformFile(string input, string output)
{
bool success = true;
// If the input file doesn't exist, fail /// <summary>
if (!File.Exists(input)) /// Ending offset for applying rule
{ /// </summary>
Globals.Logger.Error("I'm sorry but '{0}' doesn't exist!", input); public long? EndOffset { get; set; } // null if EOF
return false;
}
// Create the output directory if it doesn't already /// <summary>
Utilities.EnsureOutputDirectory(Path.GetDirectoryName(output)); /// Byte manipulation operation
/// </summary>
public HeaderSkipOperation Operation { get; set; }
Globals.Logger.User("Attempting to apply rule to '{0}'", input); /// <summary>
success = TransformStream(Utilities.TryOpenRead(input), Utilities.TryCreate(output)); /// List of matching tests in a rule
/// </summary>
public List<SkipperTest> Tests { get; set; }
// If the output file has size 0, delete it /// <summary>
if (new FileInfo(output).Length == 0) /// Filename the skipper rule lives in
{ /// </summary>
Utilities.TryDeleteFile(output); public string SourceFile { get; set; }
success = false;
}
return success; #endregion
}
/// <summary> /// <summary>
/// Transform an input stream using the given rule /// Transform an input file using the given rule
/// </summary> /// </summary>
/// <param name="input">Input stream</param> /// <param name="input">Input file name</param>
/// <param name="output">Output stream</param> /// <param name="output">Output file name</param>
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param> /// <returns>True if the file was transformed properly, false otherwise</returns>
/// <param name="keepWriteOpen">True if the underlying write stream should be kept open, false otherwise</param> public bool TransformFile(string input, string output)
/// <returns>True if the file was transformed properly, false otherwise</returns> {
public bool TransformStream(Stream input, Stream output, bool keepReadOpen = false, bool keepWriteOpen = false) bool success = true;
{
bool success = true;
// If the sizes are wrong for the values, fail // If the input file doesn't exist, fail
long extsize = input.Length; if (!File.Exists(input))
if ((Operation > HeaderSkipOperation.Bitswap && (extsize % 2) != 0) {
|| (Operation > HeaderSkipOperation.Byteswap && (extsize % 4) != 0) Globals.Logger.Error("I'm sorry but '{0}' doesn't exist!", input);
|| (Operation > HeaderSkipOperation.Bitswap && (StartOffset == null || StartOffset % 2 == 0))) return false;
{ }
Globals.Logger.Error("The stream did not have the correct size to be transformed!");
return false;
}
// Now read the proper part of the file and apply the rule // Create the output directory if it doesn't already
BinaryWriter bw = null; Utilities.EnsureOutputDirectory(Path.GetDirectoryName(output));
BinaryReader br = null;
try
{
Globals.Logger.User("Applying found rule to input stream");
bw = new BinaryWriter(output);
br = new BinaryReader(input);
// Seek to the beginning offset Globals.Logger.User("Attempting to apply rule to '{0}'", input);
if (StartOffset == null) success = TransformStream(Utilities.TryOpenRead(input), Utilities.TryCreate(output));
{
success = false;
}
else if (Math.Abs((long)StartOffset) > input.Length)
{
success = false;
}
else if (StartOffset > 0)
{
input.Seek((long)StartOffset, SeekOrigin.Begin);
}
else if (StartOffset < 0)
{
input.Seek((long)StartOffset, SeekOrigin.End);
}
// Then read and apply the operation as you go // If the output file has size 0, delete it
if (success) if (new FileInfo(output).Length == 0)
{ {
byte[] buffer = new byte[4]; Utilities.TryDeleteFile(output);
int pos = 0; success = false;
while (input.Position < (EndOffset ?? input.Length) }
&& input.Position < input.Length)
{
byte b = br.ReadByte();
switch (Operation)
{
case HeaderSkipOperation.Bitswap:
// http://stackoverflow.com/questions/3587826/is-there-a-built-in-function-to-reverse-bit-order
uint r = b;
int s = 7;
for (b >>= 1; b != 0; b >>= 1)
{
r <<= 1;
r |= (byte)(b & 1);
s--;
}
r <<= s;
buffer[pos] = (byte)r;
break;
case HeaderSkipOperation.Byteswap:
if (pos % 2 == 1)
{
buffer[pos - 1] = b;
}
if (pos % 2 == 0)
{
buffer[pos + 1] = b;
}
break;
case HeaderSkipOperation.Wordswap:
buffer[3 - pos] = b;
break;
case HeaderSkipOperation.WordByteswap:
buffer[(pos + 2) % 4] = b;
break;
case HeaderSkipOperation.None:
default:
buffer[pos] = b;
break;
}
// Set the buffer position to default write to return success;
pos = (pos + 1) % 4; }
// If we filled a buffer, flush to the stream /// <summary>
if (pos == 0) /// Transform an input stream using the given rule
{ /// </summary>
bw.Write(buffer); /// <param name="input">Input stream</param>
bw.Flush(); /// <param name="output">Output stream</param>
buffer = new byte[4]; /// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
} /// <param name="keepWriteOpen">True if the underlying write stream should be kept open, false otherwise</param>
} /// <returns>True if the file was transformed properly, false otherwise</returns>
// If there's anything more in the buffer, write only the left bits public bool TransformStream(Stream input, Stream output, bool keepReadOpen = false, bool keepWriteOpen = false)
for (int i = 0; i < pos; i++) {
{ bool success = true;
bw.Write(buffer[i]);
}
}
}
catch (Exception ex)
{
Globals.Logger.Error(ex.ToString());
return false;
}
finally
{
// If we're not keeping the read stream open, dispose of the binary reader
if (!keepReadOpen)
{
br?.Dispose();
}
// If we're not keeping the write stream open, dispose of the binary reader // If the sizes are wrong for the values, fail
if (!keepWriteOpen) long extsize = input.Length;
{ if ((Operation > HeaderSkipOperation.Bitswap && (extsize % 2) != 0)
bw?.Dispose(); || (Operation > HeaderSkipOperation.Byteswap && (extsize % 4) != 0)
} || (Operation > HeaderSkipOperation.Bitswap && (StartOffset == null || StartOffset % 2 == 0)))
} {
Globals.Logger.Error("The stream did not have the correct size to be transformed!");
return false;
}
return success; // Now read the proper part of the file and apply the rule
} BinaryWriter bw = null;
} BinaryReader br = null;
try
{
Globals.Logger.User("Applying found rule to input stream");
bw = new BinaryWriter(output);
br = new BinaryReader(input);
/// <summary> // Seek to the beginning offset
/// Intermediate class for storing Skipper Test information if (StartOffset == null)
/// </summary> {
public struct SkipperTest success = false;
{ }
public HeaderSkipTest Type; else if (Math.Abs((long)StartOffset) > input.Length)
public long? Offset; // null is EOF {
public byte[] Value; success = false;
public bool Result; }
public byte[] Mask; else if (StartOffset > 0)
public long? Size; // null is PO2, "power of 2" filesize {
public HeaderSkipTestFileOperator Operator; input.Seek((long)StartOffset, SeekOrigin.Begin);
} }
else if (StartOffset < 0)
{
input.Seek((long)StartOffset, SeekOrigin.End);
}
// Then read and apply the operation as you go
if (success)
{
byte[] buffer = new byte[4];
int pos = 0;
while (input.Position < (EndOffset ?? input.Length)
&& input.Position < input.Length)
{
byte b = br.ReadByte();
switch (Operation)
{
case HeaderSkipOperation.Bitswap:
// http://stackoverflow.com/questions/3587826/is-there-a-built-in-function-to-reverse-bit-order
uint r = b;
int s = 7;
for (b >>= 1; b != 0; b >>= 1)
{
r <<= 1;
r |= (byte)(b & 1);
s--;
}
r <<= s;
buffer[pos] = (byte)r;
break;
case HeaderSkipOperation.Byteswap:
if (pos % 2 == 1)
{
buffer[pos - 1] = b;
}
if (pos % 2 == 0)
{
buffer[pos + 1] = b;
}
break;
case HeaderSkipOperation.Wordswap:
buffer[3 - pos] = b;
break;
case HeaderSkipOperation.WordByteswap:
buffer[(pos + 2) % 4] = b;
break;
case HeaderSkipOperation.None:
default:
buffer[pos] = b;
break;
}
// Set the buffer position to default write to
pos = (pos + 1) % 4;
// If we filled a buffer, flush to the stream
if (pos == 0)
{
bw.Write(buffer);
bw.Flush();
buffer = new byte[4];
}
}
// If there's anything more in the buffer, write only the left bits
for (int i = 0; i < pos; i++)
{
bw.Write(buffer[i]);
}
}
}
catch (Exception ex)
{
Globals.Logger.Error(ex.ToString());
return false;
}
finally
{
// If we're not keeping the read stream open, dispose of the binary reader
if (!keepReadOpen)
{
br?.Dispose();
}
// If we're not keeping the write stream open, dispose of the binary reader
if (!keepWriteOpen)
{
bw?.Dispose();
}
}
return success;
}
}
/// <summary>
/// Intermediate class for storing Skipper Test information
/// </summary>
public struct SkipperTest
{
/// <summary>
/// Type of test to be run
/// </summary>
public HeaderSkipTest Type { get; set; }
/// <summary>
/// File offset to run the test
/// </summary>
public long? Offset { get; set; } // null is EOF
/// <summary>
/// Static value to be checked at the offset
/// </summary>
public byte[] Value { get; set; }
/// <summary>
/// Determines whether a pass or failure is expected
/// </summary>
public bool Result { get; set; }
/// <summary>
/// Byte mask to be applied to the tested bytes
/// </summary>
public byte[] Mask { get; set; }
/// <summary>
/// Expected size of the input byte array, used with the Operator
/// </summary>
public long? Size { get; set; } // null is PO2, "power of 2" filesize
/// <summary>
/// Expected range value for the input byte array size, used with Size
/// </summary>
public HeaderSkipTestFileOperator Operator { get; set; }
}
} }