Browse Source

Merge downstream

Herman Schoenfeld 7 years ago
parent
commit
c2311bec69

+ 37 - 11
src/libraries/hashlib4pascal/Hash128/HlpMurmurHash3_x64_128.pas

@@ -36,6 +36,7 @@ type
 
     procedure ByteUpdate(a_b: Byte); inline;
     procedure Finish();
+    procedure ProcessPendings();
 
 {$REGION 'Consts'}
 
@@ -76,13 +77,11 @@ implementation
 
 { TMurmurHash3_x64_128 }
 
-procedure TMurmurHash3_x64_128.ByteUpdate(a_b: Byte);
+procedure TMurmurHash3_x64_128.ProcessPendings;
 var
   k1, k2: UInt64;
   ptr_Fm_buf: PByte;
 begin
-  Fm_buf[Fm_idx] := a_b;
-  System.Inc(Fm_idx);
   if Fm_idx >= 16 then
   begin
     ptr_Fm_buf := PByte(Fm_buf);
@@ -111,6 +110,13 @@ begin
   end;
 end;
 
+procedure TMurmurHash3_x64_128.ByteUpdate(a_b: Byte);
+begin
+  Fm_buf[Fm_idx] := a_b;
+  System.Inc(Fm_idx);
+  ProcessPendings();
+end;
+
 constructor TMurmurHash3_x64_128.Create;
 begin
   Inherited Create(16, 16);
@@ -421,20 +427,42 @@ begin
   len := a_length;
   i := a_index;
   lIdx := 0;
-  nBlocks := len shr 4;
-
+  System.Inc(Fm_total_length, len);
   ptr_a_data := PByte(a_data);
 
+  // consume last pending bytes
+
+  if ((Fm_idx <> 0) and (a_length <> 0)) then
+  begin
+
+{$IFDEF DEBUG}
+    System.Assert(a_index = 0); // nothing would work anyways if a_index is !=0
+{$ENDIF DEBUG}
+    while ((Fm_idx < 16) and (len <> 0)) do
+    begin
+      Fm_buf[Fm_idx] := (ptr_a_data + a_index)^;
+      System.Inc(Fm_idx);
+      System.Inc(a_index);
+      System.Dec(len);
+    end;
+    if (Fm_idx = 16) then
+    begin
+      ProcessPendings;
+    end;
+  end;
+
+  nBlocks := len shr 4;
+
   // body
 
   while i < nBlocks do
   begin
 
-    k1 := TConverters.ReadBytesAsUInt64LE(ptr_a_data, lIdx);
+    k1 := TConverters.ReadBytesAsUInt64LE(ptr_a_data, a_index + lIdx);
 
     System.Inc(lIdx, 8);
 
-    k2 := TConverters.ReadBytesAsUInt64LE(ptr_a_data, lIdx);
+    k2 := TConverters.ReadBytesAsUInt64LE(ptr_a_data, a_index + lIdx);
 
     System.Inc(lIdx, 8);
 
@@ -459,11 +487,9 @@ begin
     System.Inc(i);
   end;
 
-  System.Inc(Fm_total_length, len);
-
-  offset := (i * 16);
+  offset := a_index + (i * 16);
 
-  while offset < len do
+  while (offset < (a_index + len)) do
   begin
 
     ByteUpdate(a_data[offset]);

+ 40 - 16
src/libraries/hashlib4pascal/Hash128/HlpMurmurHash3_x86_128.pas

@@ -33,8 +33,9 @@ type
     Fm_idx: Int32;
     Fm_buf: THashLibByteArray;
 
-    procedure ByteUpdate(a_b: Byte);
+    procedure ByteUpdate(a_b: Byte); inline;
     procedure Finish();
+    procedure ProcessPendings();
 
 {$REGION 'Consts'}
 
@@ -72,13 +73,11 @@ implementation
 
 { TMurmurHash3_x86_128 }
 
-procedure TMurmurHash3_x86_128.ByteUpdate(a_b: Byte);
+procedure TMurmurHash3_x86_128.ProcessPendings;
 var
   k1, k2, k3, k4: UInt32;
   ptr_Fm_buf: PByte;
 begin
-  Fm_buf[Fm_idx] := a_b;
-  System.Inc(Fm_idx);
   if Fm_idx >= 16 then
   begin
     ptr_Fm_buf := PByte(Fm_buf);
@@ -131,6 +130,13 @@ begin
   end;
 end;
 
+procedure TMurmurHash3_x86_128.ByteUpdate(a_b: Byte);
+begin
+  Fm_buf[Fm_idx] := a_b;
+  System.Inc(Fm_idx);
+  ProcessPendings();
+end;
+
 constructor TMurmurHash3_x86_128.Create;
 begin
   Inherited Create(16, 16);
@@ -465,22 +471,44 @@ begin
   len := a_length;
   i := a_index;
   lIdx := 0;
-  nBlocks := len shr 4;
-
+  System.Inc(Fm_total_length, len);
   ptr_a_data := PByte(a_data);
 
+  // consume last pending bytes
+
+  if ((Fm_idx <> 0) and (a_length <> 0)) then
+  begin
+
+{$IFDEF DEBUG}
+    System.Assert(a_index = 0); // nothing would work anyways if a_index is !=0
+{$ENDIF DEBUG}
+    while ((Fm_idx < 16) and (len <> 0)) do
+    begin
+      Fm_buf[Fm_idx] := (ptr_a_data + a_index)^;
+      System.Inc(Fm_idx);
+      System.Inc(a_index);
+      System.Dec(len);
+    end;
+    if (Fm_idx = 16) then
+    begin
+      ProcessPendings;
+    end;
+  end;
+
+  nBlocks := len shr 4;
+
   // body
 
   while i < nBlocks do
   begin
 
-    k1 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, lIdx);
+    k1 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + lIdx);
     System.Inc(lIdx, 4);
-    k2 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, lIdx);
+    k2 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + lIdx);
     System.Inc(lIdx, 4);
-    k3 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, lIdx);
+    k3 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + lIdx);
     System.Inc(lIdx, 4);
-    k4 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, lIdx);
+    k4 := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + lIdx);
     System.Inc(lIdx, 4);
 
     k1 := k1 * C1;
@@ -526,16 +554,12 @@ begin
     System.Inc(i);
   end;
 
-  System.Inc(Fm_total_length, len);
-
-  offset := (i * 16);
+  offset := a_index + (i * 16);
 
-  while offset < len do
+  while offset < (a_index + len) do
   begin
-
     ByteUpdate(a_data[offset]);
     System.Inc(offset);
-
   end;
 
 end;

+ 42 - 7
src/libraries/hashlib4pascal/Hash32/HlpMurmurHash3_x86_32.pas

@@ -204,7 +204,7 @@ procedure TMurmurHash3_x86_32.TransformBytes(a_data: THashLibByteArray;
 var
   len, nBlocks, i, offset: Int32;
   k: UInt32;
-  ptr_a_data: PByte;
+  ptr_a_data, ptr_Fm_buf: PByte;
 
 begin
 {$IFDEF DEBUG}
@@ -215,6 +215,43 @@ begin
   len := a_length;
   i := a_index;
   ptr_a_data := PByte(a_data);
+  System.Inc(Fm_total_length, len);
+
+  // consume last pending bytes
+
+  if ((Fm_idx <> 0) and (a_length <> 0)) then
+  begin
+    { *                       buf    data
+      idx = 1, len = 3 -> [0, 1[ + [0, 3[ => Block = [], buf []
+      idx = 1, len = 4 -> [0, 1[ + [0, 3[ => Block = [], buf = data[3, 4[
+      idx = 1, len = 5 -> [0, 1[ + [0, 3[ => Block = [], buf = data[3, 5[
+      ...
+      idx = 1, len = 7 -> [0, 1[ + [0, 3[ => Block = [3,7[, buf []
+      idx = 2, len = 3 -> [0, 2[ + [0, 2[ => Block = [], buf [2, 3[
+      idx = 2, len = 4 -> [0, 2[ + [0, 2[ => Block = [], buf [2, 4[
+      ...
+      idx = 2, len = 6 -> [0, 2[ + [0, 2[ => Block = [2,6[, buf []
+      * }
+
+{$IFDEF DEBUG}
+    System.Assert(a_index = 0); // nothing would work anyways if a_index is !=0
+{$ENDIF DEBUG}
+    while ((Fm_idx < 4) and (len <> 0)) do
+    begin
+      Fm_buf[Fm_idx] := (ptr_a_data + a_index)^;
+      System.Inc(Fm_idx);
+      System.Inc(a_index);
+      System.Dec(len);
+    end;
+    if (Fm_idx = 4) then
+    begin
+      ptr_Fm_buf := PByte(Fm_buf);
+      k := TConverters.ReadBytesAsUInt32LE(ptr_Fm_buf, 0);
+      TransformUInt32Fast(k);
+      Fm_idx := 0;
+    end;
+  end;
+
   nBlocks := len shr 2;
 
 
@@ -222,18 +259,16 @@ begin
 
   while i < nBlocks do
   begin
-    k := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + i * 4);
+    k := TConverters.ReadBytesAsUInt32LE(ptr_a_data, a_index + (i * 4));
 
     TransformUInt32Fast(k);
 
     System.Inc(i);
   end;
 
-  System.Inc(Fm_total_length, len);
-
-  offset := (i * 4);
-
-  while offset < len do
+  // save pending end bytes
+  offset := a_index + (i * 4);
+  while offset < (len + a_index) do
   begin
 
     ByteUpdate(a_data[offset]);

+ 37 - 12
src/libraries/hashlib4pascal/Hash64/HlpSipHash.pas

@@ -29,7 +29,7 @@ type
 
   strict private
 
-    Fm_v0, Fm_v1, Fm_v2, Fm_v3, Fm_key0, Fm_key1, Fm_total_length, F_m: UInt64;
+    Fm_v0, Fm_v1, Fm_v2, Fm_v3, Fm_key0, Fm_key1, Fm_total_length: UInt64;
     F_cr, F_fr, Fm_idx: Int32;
     Fm_buf: THashLibByteArray;
 
@@ -287,7 +287,8 @@ procedure TSipHash.TransformBytes(a_data: THashLibByteArray;
   a_index, a_length: Int32);
 var
   i, &length, iter, offset: Int32;
-  ptr_a_data: PByte;
+  ptr_a_data, ptr_Fm_buf: PByte;
+  m: UInt64;
 begin
 {$IFDEF DEBUG}
   System.Assert(a_index >= 0);
@@ -297,27 +298,51 @@ begin
   Length := a_length;
   i := a_index;
 
-  iter := Length shr 3;
   ptr_a_data := PByte(a_data);
+  System.Inc(Fm_total_length, Length);
 
-  while i < iter do
+  // consume last pending bytes
+
+  if ((Fm_idx <> 0) and (a_length <> 0)) then
   begin
-    F_m := TConverters.ReadBytesAsUInt64LE(ptr_a_data, i * 8);
-    ProcessBlock(F_m);
-    F_m := 0;
-    System.Inc(i);
+
+{$IFDEF DEBUG}
+    System.Assert(a_index = 0); // nothing would work anyways if a_index is !=0
+{$ENDIF DEBUG}
+    while ((Fm_idx < 8) and (Length <> 0)) do
+    begin
+      Fm_buf[Fm_idx] := (ptr_a_data + a_index)^;
+      System.Inc(Fm_idx);
+      System.Inc(a_index);
+      System.Dec(Length);
+    end;
+    if (Fm_idx = 8) then
+    begin
+      ptr_Fm_buf := PByte(Fm_buf);
+      m := TConverters.ReadBytesAsUInt64LE(ptr_Fm_buf, 0);
+      ProcessBlock(m);
+      Fm_idx := 0;
+    end;
   end;
 
-  System.Inc(Fm_total_length, Length);
+  iter := Length shr 3;
 
-  offset := (i * 8);
+  // body
 
-  while offset < Length do
+  while i < iter do
   begin
+    m := TConverters.ReadBytesAsUInt64LE(ptr_a_data, a_index + (i * 8));
+    ProcessBlock(m);
+    System.Inc(i);
+  end;
+
+  // save pending end bytes
+  offset := a_index + (i * 8);
 
+  while offset < (Length + a_index) do
+  begin
     ByteUpdate(a_data[offset]);
     System.Inc(offset);
-
   end;
 
 end;

+ 1 - 1
src/libraries/hashlib4pascal/Packages/FPC/HashLib4PascalPackage.lpk

@@ -22,7 +22,7 @@
     <Description Value="HashLib4Pascal is a Delphi/FPC compatible library that provides an easy to use interface for computing hashes and checksums of strings (with a specified encoding), files, streams, byte arrays and untyped data to mention but a few.
 "/>
     <License Value="MIT License"/>
-    <Version Major="2" Minor="4"/>
+    <Version Major="2" Minor="5"/>
     <Files Count="102">
       <Item1>
         <Filename Value="..\..\Base\HlpHash.pas"/>