HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Efficient binary patcher

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
patcherefficientbinary

Problem

I am currently working on a little binary patcher. My current code works fine but I do want my code to be optimized (fast) and as clean as possible. Could you all please help me review this?

IDE: Delphi 7 and XE7

```
const
OriginalByte: array [0 .. 55] of Byte = ($64, $69, $6E, $67, $20, $6D, $65,
$20, $68, $69, $73, $00, $00, $00, $00, $27, $00, $00, $28, $00, $00, $00,
$21, $00, $00, $00, $63, $6F, $6D, $70, $75, $74, $65, $72, $2E, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $27, $00, $00, $28,
$00, $00, $00, $00);

BytetoWrite: array [0 .. 55] of Byte = ($63, $68, $6F, $67, $20, $6D, $65,
$20, $68, $69, $73, $00, $00, $00, $00, $27, $00, $00, $28, $00, $00, $00,
$21, $00, $00, $00, $63, $6F, $6D, $70, $75, $74, $65, $72, $2E, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $27, $00, $00, $28,
$00, $00, $00, $06);

function CompareByteArrays(FirstArray, SecondArray: array of Byte): Boolean;

var
Counter: Integer;
begin

Result := True;
if Length(FirstArray) <> Length(SecondArray) then
begin
Result := False;
Exit;
end;

for Counter := Low(FirstArray) to High(FirstArray) do

begin
if (FirstArray[Counter]) <> (SecondArray[Counter]) then
begin
Result := False;
Exit;
end

end;

end;

procedure DoMyPatch();
var

i: Integer;
FileName: string;
input: TFileStream;

FileByteArray, ExtractedByteArray: array of Byte;

begin
FileName := 'Cute1.res';

try
input := TFileStream.Create(FileName, fmOpenReadWrite);
except
on E: Exception do
begin
ShowMessage(E.Message);
Exit;
end
end;

input.Position := 0;
SetLength(FileByteArray, input.size);
input.Read(FileByteArray[0], Length(FileByteArray));
for i := Low(FileByteArray) to High(FileByteArray) do
begin

ExtractedByteArray := Copy(FileByteArray, i, Length(OriginalByte));

if CompareByteArrays(ExtractedByteArray, OriginalByte) = True then
begin

Solution

Some notes:

  • add definition of the undeclared variables BytetoWrite, OriginalByte and how they are used/initialized



  • format your code for better readability. Left indentation is not aligned. Too many void blank lines



-
using

resource := CreateResource;
try
    // do something
finally
    FreeAndNil(resource);
end


pattern is easy to follow and it prevents unintended memory leaks nicely

  • for byte-to-byte memory compare in CompareByteArrays better use built-in CompareMem function instead of custom array traversal. In an old language runtime source codes this function was implemented in optimized assembly language



  • using Integer for file-offset is not very future-friendly idea considering that it is normal (for average end-user) today to work with video files in 4K resolution where single file size can be >4GB



  • using Memory Mapped Files for read-only file access will give you simpler code (whole file is an in-memory array) and faster I/O operations (on-demand reading managed by OS kernel code). This method can give you significant boost if the original file is big and the searched-pattern is located near the beginning of the file



  • the loop should end at High(FileByteArray) - Length(OriginalByte) (+/-1) as beyond this boundary the pattern can not be found anyway



-
you can get some speed by comparing against the original byte array just offset by the i index. Creation of the intermediate ExtractedByteArray would not be necessary (throw away, safe some memory allocation and memory copy CPU-clocks). Like this:

if CompareByteArrays(ExtractedByteArray, OriginalByte) = True then


if CompareMem(@FileByteArray[i], @OriginalByte[0], Length(OriginalByte)) = True then


assuming the i...i + Length(OriginalByte) - 1 boundaries are withing the range Low(FileByteArray)...High(FileByteArray) as mentioned in (7)

Code Snippets

resource := CreateResource;
try
    // do something
finally
    FreeAndNil(resource);
end
if CompareByteArrays(ExtractedByteArray, OriginalByte) = True then
if CompareMem(@FileByteArray[i], @OriginalByte[0], Length(OriginalByte)) = True then

Context

StackExchange Code Review Q#75234, answer score: 2

Revisions (0)

No revisions yet.