Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,25 @@ public sealed class FormatHex : PSCmdlet
[ValidateNotNullOrEmpty]
public Encoding Encoding { get; set; } = ClrFacade.GetDefaultEncoding();

/// <summary>
/// Gets and sets count of bytes to read from the input stream.
/// </summary>
[Parameter()]
[ValidateRange(ValidateRangeKind.Positive)]
public Int64 Count { get; set; } = Int64.MaxValue;

/// <summary>
/// Gets and sets offset of bytes to start reading the input stream from.
/// </summary>
[Parameter()]
[ValidateRange(ValidateRangeKind.NonNegative)]
public Int64 Offset { get; set; }

/// <summary>
/// This parameter is no-op.
/// </summary>
[Parameter(ParameterSetName = "ByInputObject")]
[Parameter(ParameterSetName = "ByInputObject", DontShow = true)]
[Obsolete("Raw parameter is deprecated.", true)]
public SwitchParameter Raw { get; set; }

#endregion
Expand Down Expand Up @@ -157,42 +172,36 @@ private void ProcessPath(List<string> pathsToProcess)

/// <summary>
/// Creates a binary reader that reads the file content into a buffer (byte[]) 16 bytes at a time, and
/// passes a copy of that array on to the ConvertToHexidecimal method to output.
/// passes a copy of that array on to the WriteHexidecimal method to output.
/// </summary>
/// <param name="path"></param>
private void ProcessFileContent(string path)
{
byte[] buffer = new byte[BUFFERSIZE];
Span<byte> buffer = stackalloc byte[BUFFERSIZE];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!


try
{
using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read)))
using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)))
Copy link
Collaborator

@rkeithhill rkeithhill Sep 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

{
UInt32 offset = 0;
Int64 offset = Offset;
Int32 bytesRead = 0;
Int64 count = 0;

while ((bytesRead = reader.Read(buffer, 0, BUFFERSIZE)) > 0)
reader.BaseStream.Position = Offset;

while ((bytesRead = reader.Read(buffer)) > 0)
{
if (bytesRead == BUFFERSIZE)
{
// We are reusing the same buffer so if we save the output to a variable, the variable
// will just contain multiple references to the same buffer memory space (containing only the
// last bytes of the file read). Copying the buffer allows us to pass the values on without
// overwriting previous values.
byte[] copyOfBuffer = new byte[16];
Array.Copy(buffer, 0, copyOfBuffer, 0, bytesRead);
ConvertToHexidecimal(copyOfBuffer, path, offset);
}
else
count += bytesRead;
if (count > Count)
{
// Handle the case of a partial (and probably last) buffer. Copies the bytes read into a new,
// shorter array so we do not have the extra bytes from the previous pass through at the end.
byte[] remainingBytes = new byte[bytesRead];
Array.Copy(buffer, 0, remainingBytes, 0, bytesRead);
ConvertToHexidecimal(remainingBytes, path, offset);
bytesRead -= (int)(count - Count);
WriteHexidecimal(buffer.Slice(0, bytesRead), path, offset);
break;
}
// Update offset value.
offset += (UInt32)bytesRead;

WriteHexidecimal(buffer.Slice(0, bytesRead), path, offset);

offset += bytesRead;
}
}
}
Expand Down Expand Up @@ -221,85 +230,86 @@ private void ProcessFileContent(string path)

/// <summary>
/// Creates a byte array from the object passed to the cmdlet (based on type) and passes
/// that array on to the ConvertToHexidecimal method to output.
/// that array on to the WriteHexidecimal method to output.
/// </summary>
/// <param name="inputObject"></param>
private void ProcessObjectContent(PSObject inputObject)
{
Object obj = inputObject.BaseObject;
byte[] inputBytes = null;
if (obj is System.IO.FileSystemInfo)
{
string[] path = { ((FileSystemInfo)obj).FullName };
List<string> pathsToProcess = ResolvePaths(path, true);
ProcessPath(pathsToProcess);
}

else if (obj is string)
switch (obj)
{
string inputString = obj.ToString();
inputBytes = Encoding.GetBytes(inputString);
}
case System.IO.FileSystemInfo fsi:
string[] path = { fsi.FullName };
List<string> pathsToProcess = ResolvePaths(path, true);
ProcessPath(pathsToProcess);
return;
case string str:
inputBytes = Encoding.GetBytes(str);
break;
case byte b:
inputBytes = new byte[] { b };
break;
case byte[] byteArray:
inputBytes = byteArray;
break;
case Int32 iInt32:
inputBytes = BitConverter.GetBytes(iInt32);
break;
case Int32[] i32s:
int i32 = 0;
inputBytes = new byte[sizeof(Int32) * i32s.Length];
Span<byte> inputStreamArray32 = inputBytes;

foreach (Int32 value in i32s)
{
BitConverter.TryWriteBytes(inputStreamArray32.Slice(i32), value);
i32 += sizeof(Int32);
}

else if (obj is byte)
{
inputBytes = new byte[] { (byte)obj };
}
break;
case Int64 iInt64:
inputBytes = BitConverter.GetBytes(iInt64);
break;
case Int64[] inputInt64s:
int i64 = 0;
inputBytes = new byte[sizeof(Int64) * inputInt64s.Length];
Span<byte> inputStreamArray64 = inputBytes;

else if (obj is byte[])
{
inputBytes = ((byte[])obj);
}

else if (obj is Int32)
{
inputBytes = BitConverter.GetBytes((Int32)obj);
}
foreach (Int64 value in inputInt64s)
{
BitConverter.TryWriteBytes(inputStreamArray64.Slice(i64), value);
i64 += sizeof(Int64);
}

else if (obj is Int32[])
{
List<byte> inputStreamArray = new List<byte>();
Int32[] inputInts = (Int32[])obj;
foreach (Int32 value in inputInts)
break;
// If the object type is not supported, throw an error. Once Serialization is
// available on CoreCLR, other types will be supported.
default:
{
byte[] tempBytes = BitConverter.GetBytes(value);
inputStreamArray.AddRange(tempBytes);
string errorMessage = StringUtil.Format(UtilityCommonStrings.FormatHexTypeNotSupported, obj.GetType());
ErrorRecord errorRecord = new ErrorRecord(new ArgumentException(errorMessage),
"FormatHexTypeNotSupported",
ErrorCategory.InvalidArgument,
obj.GetType());
WriteError(errorRecord);
break;
}
inputBytes = inputStreamArray.ToArray();
}

else if (obj is Int64)
{
inputBytes = BitConverter.GetBytes((Int64)obj);
}

else if (obj is Int64[])
if (inputBytes != null)
{
List<byte> inputStreamArray = new List<byte>();
Int64[] inputInts = (Int64[])obj;
foreach (Int64 value in inputInts)
int offset = Math.Min(inputBytes.Length, Offset < (long)int.MaxValue ? (int)Offset : int.MaxValue);
int count = Math.Min(inputBytes.Length - offset, Count < (long)int.MaxValue ? (int)Count : int.MaxValue);
if (offset != 0 || count != inputBytes.Length)
{
byte[] tempBytes = BitConverter.GetBytes(value);
inputStreamArray.AddRange(tempBytes);
WriteHexidecimal(inputBytes.AsSpan().Slice(offset, count), null, 0);
}
else
{
WriteHexidecimal(inputBytes, null, 0);
}
inputBytes = inputStreamArray.ToArray();
}

// If the object type is not supported, throw an error. Once Serialization is
// available on CoreCLR, other types will be supported.
else
{
string errorMessage = StringUtil.Format(UtilityCommonStrings.FormatHexTypeNotSupported, obj.GetType());
ErrorRecord errorRecord = new ErrorRecord(new ArgumentException(errorMessage),
"FormatHexTypeNotSupported",
ErrorCategory.InvalidArgument,
obj.GetType());
WriteError(errorRecord);
}

if (inputBytes != null)
{
ConvertToHexidecimal(inputBytes, null, 0);
}
}

Expand All @@ -308,18 +318,21 @@ private void ProcessObjectContent(PSObject inputObject)
#region Output

/// <summary>
/// Outputs the hexadecimial representaion of the of the input data.
/// Outputs the hexadecimial representaion of the input data.
/// </summary>
/// <param name="inputBytes"></param>
/// <param name="path"></param>
/// <param name="offset"></param>
private void ConvertToHexidecimal(byte[] inputBytes, string path, UInt32 offset)
/// <param name="inputBytes">Bytes for the hexadecimial representaion.</param>
/// <param name="path">File path.</param>
/// <param name="offset">Offset in the file.</param>
private void WriteHexidecimal(Span<byte> inputBytes, string path, Int64 offset)
{
if (inputBytes != null)
{
ByteCollection byteCollectionObject = new ByteCollection(offset, inputBytes, path);
WriteObject(byteCollectionObject);
}
ByteCollection byteCollectionObject = new ByteCollection((UInt64)offset, inputBytes.ToArray(), path);
WriteObject(byteCollectionObject);
}

private void WriteHexidecimal(byte[] inputBytes, string path, Int64 offset)
{
ByteCollection byteCollectionObject = new ByteCollection((UInt64)offset, inputBytes, path);
WriteObject(byteCollectionObject);
}

#endregion
Expand Down
Loading