OSDN Git Service

Updated Delphi language bindings.
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 27 Mar 2016 18:30:28 +0000 (20:30 +0200)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 27 Mar 2016 18:30:28 +0000 (20:30 +0200)
.gitignore
bindings/Delphi/example/Example.dpr
bindings/Delphi/example/src/Main.dfm
bindings/Delphi/example/src/Main.pas
bindings/Delphi/native/MHashDelphi384.cpp
bindings/Delphi/wrapper/MHash384.pas [moved from bindings/Delphi/example/src/MHash384.pas with 71% similarity]

index a783acc..332e179 100644 (file)
@@ -7,6 +7,7 @@
 *.~dfm
 *.~dpr
 *.~pas
+*.~ddp
 /bin
 /bindings/Delphi/example/bin/*.dll
 /bindings/Delphi/example/bin/*.exe
index 9eee4e0..c49ce06 100644 (file)
@@ -2,13 +2,13 @@ program Example;
 
 uses
   Forms,
-  Main in 'src\Main.pas' {Form1},
-  MHash384 in 'src\MHash384.pas';
+  Main in 'src\Main.pas' {MainForm},
+  MHash384 in '..\wrapper\MHash384.pas';
 
 {$R *.res}
 
 begin
   Application.Initialize;
-  Application.CreateForm(TForm1, Form1);
+  Application.CreateForm(TMainForm, MainForm);
   Application.Run;
 end.
index f6414cf..ac16e55 100644 (file)
@@ -1,9 +1,9 @@
-object Form1: TForm1
-  Left = 345
-  Top = 125
-  Width = 1305
-  Height = 675
-  Caption = 'Form1'
+object MainForm: TMainForm
+  Left = 608
+  Top = 189
+  Width = 872
+  Height = 271
+  Caption = 'MHashDelphi384 - Example App'
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText
@@ -11,16 +11,95 @@ object Form1: TForm1
   Font.Name = 'MS Sans Serif'
   Font.Style = []
   OldCreateOrder = False
+  Position = poScreenCenter
+  OnCloseQuery = FormCloseQuery
   OnCreate = FormCreate
+  DesignSize = (
+    856
+    232)
   PixelsPerInch = 96
   TextHeight = 13
-  object Button1: TButton
+  object Label1: TLabel
     Left = 8
     Top = 8
-    Width = 75
+    Width = 58
+    Height = 13
+    Caption = 'Input File:'
+    Font.Charset = DEFAULT_CHARSET
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+  end
+  object Label2: TLabel
+    Left = 8
+    Top = 64
+    Width = 65
+    Height = 13
+    Caption = 'File Digest:'
+    Font.Charset = DEFAULT_CHARSET
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+  end
+  object Button_Compute: TButton
+    Left = 711
+    Top = 183
+    Width = 123
     Height = 25
-    Caption = 'Button1'
+    Anchors = [akRight, akBottom]
+    Caption = 'Compute Hash'
+    TabOrder = 1
+    OnClick = Button_ComputeClick
+  end
+  object Edit_InputFile: TEdit
+    Left = 8
+    Top = 24
+    Width = 825
+    Height = 21
+    Anchors = [akLeft, akTop, akRight]
+    ReadOnly = True
+    TabOrder = 2
+  end
+  object Edit_FileDigest: TEdit
+    Left = 8
+    Top = 80
+    Width = 825
+    Height = 22
+    Anchors = [akLeft, akTop, akRight]
+    Font.Charset = DEFAULT_CHARSET
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'Courier New'
+    Font.Style = []
+    ParentFont = False
+    ReadOnly = True
+    TabOrder = 3
+  end
+  object Button_Browse: TButton
+    Left = 575
+    Top = 183
+    Width = 121
+    Height = 25
+    Anchors = [akRight, akBottom]
+    Caption = 'Browse File'
     TabOrder = 0
-    OnClick = Button1Click
+    OnClick = Button_BrowseClick
+  end
+  object ProgressBar: TProgressBar
+    Left = 8
+    Top = 128
+    Width = 825
+    Height = 17
+    Anchors = [akLeft, akTop, akRight]
+    Smooth = True
+    TabOrder = 4
+  end
+  object OpenDialog: TOpenDialog
+    Left = 8
+    Top = 168
   end
 end
index 8b35370..6473259 100644 (file)
 
 unit Main;
 
+{===========================================================================}
+{ INTERFACE                                                                 }
+{===========================================================================}
+
 interface
 
 uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, MHash384, StdCtrls;
+  Dialogs, MHash384, StdCtrls, ComCtrls;
 
 type
-  TForm1 = class(TForm)
-    Button1: TButton;
-    procedure Button1Click(Sender: TObject);
+  TMainForm = class(TForm)
+    Button_Compute: TButton;
+    Edit_InputFile: TEdit;
+    Label1: TLabel;
+    Label2: TLabel;
+    Edit_FileDigest: TEdit;
+    Button_Browse: TButton;
+    ProgressBar: TProgressBar;
+    OpenDialog: TOpenDialog;
     procedure FormCreate(Sender: TObject);
+    procedure Button_BrowseClick(Sender: TObject);
+    procedure Button_ComputeClick(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+  protected
+    procedure ThreadTerminated(Sender: TObject);
+    procedure ProgressChanged(progress: Integer);
   private
     { Private-Deklarationen }
   public
     { Public-Deklarationen }
   end;
 
+type
+  TProgressEvent = procedure(progress: Integer) of object;
+
+type
+  TComputeThread = class(TThread)
+  private
+    hwnd: HWND;
+    inputFile, hashString: String;
+    progressValue: Integer;
+    progressEvent: TProgressEvent;
+  public
+    constructor Create(const hwnd: HWND; const inputFile: String);
+    function GetResult: String;
+    property OnProgress: TProgressEvent read progressEvent write progressEvent;
+  protected
+    procedure Execute(); override;
+    function FileSize64(const fileName: string): UInt64;
+    procedure SetProgress(const processed: UInt64; const totalSize: UInt64);
+    function ByteToHex(input: TByteArray):String;
+    procedure UpdateProgress;
+  end;
+
 var
-  Form1: TForm1;
+  MainForm: TMainForm;
+
+{===========================================================================}
+{ IMPLEMENTATION                                                            }
+{===========================================================================}
 
 implementation
 
 {$R *.dfm}
 
-procedure TForm1.Button1Click(Sender: TObject);
-var
-  mhash: TMHash384;
-begin
-  mhash := TMHash384.Create();
-end;
+{----------------------------------------------}
+{ Main Form                                    }
+{----------------------------------------------}
 
-procedure TForm1.FormCreate(Sender: TObject);
+procedure TMainForm.FormCreate(Sender: TObject);
 var
   Version: TMHash384Ver;
 begin
+  Constraints.MinHeight := Height;
+  Constraints.MinWidth := Width;
   FillChar(Version, SizeOf(TMHash384Ver), #0);
   TMHash384.GetVer(Version);
   Caption := 'MHashDelphi384 - Example App v' + Format('%d.%d.%d', [Version.Major, Version.Minor, Version.Patch]);
 end;
 
+procedure TMainForm.Button_BrowseClick(Sender: TObject);
+begin
+  if OpenDialog.Execute then
+  begin
+    Edit_FileDigest.Text := '';
+    Edit_InputFile.Text := OpenDialog.FileName;
+    ProgressBar.Position := 0;
+  end;
+end;
+
+procedure TMainForm.Button_ComputeClick(Sender: TObject);
+var
+  thread: TComputeThread;
+begin
+  Button_Browse.Enabled := False;
+  Button_Compute.Enabled := False;
+  ProgressBar.Position := 0;
+  Edit_FileDigest.Text := 'Working, please wait...';
+
+  thread := TComputeThread.Create(Self.WindowHandle, Edit_InputFile.Text);
+  thread.OnProgress := ProgressChanged;
+  thread.OnTerminate := ThreadTerminated;
+  thread.Resume;
+end;
+
+procedure TMainForm.ProgressChanged(progress: Integer);
+begin
+  ProgressBar.Position := progress;
+end;
+
+procedure TMainForm.ThreadTerminated(Sender: TObject);
+begin
+  if Sender is TComputeThread then
+  begin
+    Edit_FileDigest.Text := (Sender as TComputeThread).GetResult();
+    Button_Compute.Enabled := True;
+    Button_Browse.Enabled := True;
+  end;
+end;
+
+procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  CanClose := Button_Compute.Enabled and Button_Browse.Enabled;
+end;
+
+{----------------------------------------------}
+{ Compute Thread                               }
+{----------------------------------------------}
+
+constructor TComputeThread.Create(const hwnd: HWND; const inputFile: String);
+begin
+  inherited Create(True);
+  Self.hwnd := hwnd;
+  Self.inputFile := inputFile;
+  ReturnValue := 0;
+  progressEvent := nil;
+end;
+
+function TComputeThread.GetResult: String;
+var
+  exitCode: Cardinal;
+begin
+  Result := hashString;
+end;
+
+procedure TComputeThread.Execute();
+var
+  digest: TMHash384;
+  inputFile: File;
+  buffer, result: TByteArray;
+  count, spinner: Integer;
+  totalSize, processed: UInt64;
+begin
+  inherited;
+  try
+    ReturnValue := 0;
+    processed := 0;
+    spinner := 0;
+
+    SetLength(buffer, 4096);
+    SetProgress(0, 100);
+    totalSize := FileSize64(Self.inputFile);
+
+    AssignFile(inputFile, Self.inputFile);
+    FileMode := fmOpenRead;
+    Reset(inputFile, 1);
+
+    try
+      digest := TMHash384.Create();
+      while not Eof(inputFile) do
+      begin
+        BlockRead(inputFile, buffer[0], Length(buffer), count);
+        if count > 0 then
+        begin
+          digest.Update(buffer, 0, count);
+          spinner := spinner + 1;
+          processed := processed + count;
+          if spinner >= 100 then
+          begin
+            SetProgress(processed, totalSize);
+            spinner := 0;
+          end;
+        end;
+      end;
+      digest.Result(result);
+      HashString := ByteToHex(result);
+      ReturnValue := 1;
+    finally
+      CloseFile(inputFile);
+      digest.Destroy();
+      SetProgress(100, 100);
+    end;
+  except
+     on E: Exception do
+     begin
+       MessageBox(self.hwnd, PAnsiChar('Failed to open input file!'#10#10'Details:'#10 + E.Message), PAnsiChar(String(E.ClassName)), MB_ICONERROR or MB_SYSTEMMODAL);
+       Exit;
+     end;
+  end;
+end;
+
+function TComputeThread.FileSize64(const fileName: string): UInt64;
+var
+  F: TSearchRec;
+begin
+  Result := 0;
+  if FindFirst(fileName, faAnyFile, F) = 0 then
+  begin
+    try
+      Result := UInt64(F.FindData.nFileSizeLow) or (UInt64(F.FindData.nFileSizeHigh) shl 32);
+    finally
+      FindClose(F);
+    end;
+  end;
+end;
+
+procedure TComputeThread.UpdateProgress;
+begin
+  if Assigned(progressEvent) then
+  begin
+    progressEvent(progressValue);
+  end;
+end;
+
+
+procedure TComputeThread.SetProgress(const processed: UInt64; const totalSize: UInt64);
+var
+  nextProgress: Integer;
+  totalSizeDbl, processedDbl: Double;
+begin
+  if (processed > 0) and (totalSize > 0) then
+  begin
+    totalSizeDbl := totalSize;
+    processedDbl := processed;
+    nextProgress := Round((processedDbl / totalSizeDbl) * 100.0);
+  end else
+  begin
+    progressValue := 0;
+  end;
+
+  if nextProgress <> progressValue then
+  begin
+    progressValue := nextProgress;
+    Synchronize(updateProgress);
+  end;
+end;
+
+function TComputeThread.ByteToHex(input: TByteArray):String;
+const
+  digits:array[0..15] of char='0123456789ABCDEF';
+var
+  i: Cardinal;
+begin
+  for i := 0 to Length(input)-1 do
+  begin
+    Result := Result + digits[input[i] shr 4] + digits[input[i] and $0F];
+  end;
+end;
+
 end.
index 0b96e64..909f07d 100644 (file)
@@ -37,12 +37,12 @@ EXPORT_FUNC(mhash384_update, void, const uintptr_t instance, uint8_t *const inpu
        reinterpret_cast<mhash::MHash384*>(instance)->update(input + offset, len);
 }
 
-EXPORT_FUNC(mhash384_finalize, void, const uintptr_t instance, uint8_t *const buffer)
+EXPORT_FUNC(mhash384_result, void, const uintptr_t instance, uint8_t *const buffer)
 {
        reinterpret_cast<mhash::MHash384*>(instance)->finalize(buffer);
 }
 
-EXPORT_FUNC(mhash384_cleanup, void, const uintptr_t instance)
+EXPORT_FUNC(mhash384_freeup, void, const uintptr_t instance)
 {
        delete reinterpret_cast<mhash::MHash384*>(instance);
 }
similarity index 71%
rename from bindings/Delphi/example/src/MHash384.pas
rename to bindings/Delphi/wrapper/MHash384.pas
index ed43fd8..bb6a69d 100644 (file)
@@ -27,6 +27,9 @@ unit MHash384;
 interface
 
 type
+  TByteArray = array of byte;
+
+type
   TMHash384Ver = record
     Major: LongWord;
     Minor: LongWord;
@@ -37,11 +40,18 @@ type
   TMHash384 = Class
   public
     constructor Create();
+    destructor Destroy(); override;
+    procedure Update(const input: TByteArray); overload;
+    procedure Update(const input: TByteArray; const offset: LongWord; const len: LongWord); overload;
+    procedure Result(var hash: TByteArray);
     class procedure GetVer(var Version: TMHash384Ver);
   private
     handle: Pointer;
   end;
 
+const
+  MHASH384_LEN: Cardinal = 48;
+
 {===========================================================================}
 { IMPLEMENTATION                                                            }
 {===========================================================================}
@@ -54,8 +64,11 @@ implementation
 
 const MHash384Lib = 'MHashDelphi384.dll';
 
-function mhash384_native_create(): Pointer; cdecl; external MHash384Lib name 'mhash384_create';
+function  mhash384_native_create(): Pointer; cdecl; external MHash384Lib name 'mhash384_create';
 procedure mhash384_native_getver(major: PLongWord; minor: PLongWord; patch: PLongWord); cdecl; external MHash384Lib name 'mhash384_getver';
+procedure mhash384_native_update(handle: Pointer; const buffer: PByte; offset: LongWord; len: LongWord); cdecl; external MHash384Lib name 'mhash384_update';
+procedure mhash384_native_result(handle: Pointer; buffer: PByte); cdecl; external MHash384Lib name 'mhash384_result';
+procedure mhash384_native_freeup(handle: Pointer); cdecl; external MHash384Lib name 'mhash384_freeup';
 
 {----------------------------------------------}
 { Public Functions                             }
@@ -66,6 +79,31 @@ begin
   handle := mhash384_native_create();
 end;
 
+destructor TMHash384.Destroy();
+begin
+  if Assigned(handle) then
+  begin
+    mhash384_native_freeup(handle);
+    handle := nil;
+  end;
+end;
+
+procedure TMHash384.Update(const input: TByteArray);
+begin
+  Update(input, 0, Length(input));
+end;
+
+procedure TMHash384.Update(const input: TByteArray; const offset: LongWord; const len: LongWord);
+begin
+  mhash384_native_update(handle, @input[0], offset, len);
+end;
+
+procedure TMHash384.Result(var hash: TByteArray);
+begin
+  SetLength(hash, MHASH384_LEN);
+  mhash384_native_result(handle, @hash[0]);
+end;
+
 class procedure TMHash384.GetVer(var Version: TMHash384Ver);
 begin
   mhash384_native_getver(@Version.major, @Version.minor, @Version.patch);