Sodele, ich habe die Methode nochmals überarbeitet und jetzt kann man auch die vollen 32bit für einen Integer auslesen, ohne dass es einem um die Ohren fliegt
Im
Debug-Mode bleibt es bei ca.
16ms und im
Release-Mode sind es ca.
7ms (jeweils für 1.000.000 Abfragen). Ich denke mal, das müsste von der Geschwindigkeit ausreichen
Delphi-Quellcode:
unit BaseData;
interface
uses
System.SysUtils;
type
TBaseData =
class
private
FData : TBytes;
protected
function GetData(
const Index : integer ) : integer;
public
constructor Create( AData : TBytes );
end;
implementation
{ TBaseData }
constructor TBaseData.Create( AData : TBytes );
begin
inherited Create;
FData := AData;
end;
function TBaseData.GetData(
const Index : integer ) : integer;
var
LBitCount : integer;
LBitOffset : integer;
LByteOffset : integer;
LByteIdx : PByte;
LMask : Byte;
begin
LBitCount :=
index and $FF;
if LBitCount > 32
then
raise EArgumentOutOfRangeException.CreateFmt( '
Index %x contains invalid BitWidth %x', [
index, LBitCount] );
LBitOffset := (
index shr 8 )
and $FFFFFF;
LByteOffset := LBitOffset
div 8;
LBitOffset := LBitOffset - LByteOffset * 8;
LByteIdx := @FData[LByteOffset];
{ TODO : RangeCheck for LByteOffset }
if LBitCount > 0
then
begin
LMask := ( 1
shl ( 8 - LBitOffset ) ) - 1;
Result := ( LByteIdx^
and LMask );
LBitCount := LBitCount - ( 8 - LBitOffset );
end
else
begin
Result := 0;
Exit;
end;
while LBitCount >= 8
do
begin
Inc( LByteIdx );
Result := Result
shl 8;
Result := Result
or LByteIdx^;
LBitCount := LBitCount - 8;
end;
if LBitCount > 0
then
begin
Inc( LByteIdx );
Result := Result
shl LBitCount;
LMask := ( 1
shl ( 8 - LBitOffset ) ) - 1;
Result := Result
or ( ( LByteIdx^
shr ( 8 - LBitCount ) )
and LMask );
end;
end;
end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ea 0a 4c 14 0d b6 3a a4 c1 c5 b9
dc 90 9d f0 e9 de 13 da 60)