Componentes.Terceros.RemObj.../internal/5.0.23.613/1/RemObjects SDK for Delphi/Source/RODEC/uRODECUtil.pas
david 2824855ea7 - Modificación del paquete RemObjects_Core_D10 para que sea un paquete de runtime/designtime (antes era designtime sólo)
- Recompilación en Delphi10 de todos los paquetes de RO para generar las DCU's en Lib\D10
- Recompilación en Delphi10 de todos los paquetes de DA para generar las DCU's en Lib\D10

git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.RemObjects@9 b6239004-a887-0f4b-9937-50029ccdca16
2007-09-10 14:06:19 +00:00

1673 lines
48 KiB
ObjectPascal

{Copyright: Hagen Reddmann mailto:HaReddmann@AOL.COM
Author: Hagen Reddmann
Remarks: freeware, but this Copyright must be included
known Problems: none
Version: 3.0, Delphi Encryption Compendium
Delphi 2-4, BCB 3-4, designed and testet under D3 and D4
Description: Utilitys for the DEC Packages
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
unit uRODECUtil;
interface
uses SysUtils, Classes;
{$I uROVer.inc}
{$I RemObjects.inc}
const
// String Formats
fmtDEFAULT = -1; // use DefaultStringFormat
fmtNONE = 0; // allways an Empty String, nothing Action
fmtCOPY = 1; // One to One binary (input = output)
fmtHEX = 16; // Hexadecimal
fmtHEXL = 1016; // Hexadecimal lowercase
fmtMIME64 = $1064; // MIME Base 64
fmtUU = $5555; // UU Coding $5555 = 'UU'
fmtXX = $5858; // XX Coding $5858 = 'XX'
// 2 - 64 reserved for Formats to the Base 2 - 64
// over 1000 all other Formats
type
{$IFNDEF VER_D4H}
LongWord = LongInt;
PLongWord = ^LongWord;
{$ENDIF}
PByte = ^Byte;
PInteger = ^LongWord;
PWord = ^Word;
PIntArray = ^TIntArray;
TIntArray = array[0..1023] of LongWord;
EROProtection = class(Exception);
EROStringFormat = class(Exception);
// basic Class for all Protection Classes, TROCipher, TROHash, TRORandom
// TProtect can build a chain with varios Encryption Algos.
// i.E. CodeBuffer() can en/decode the Buffer with more as one RO_Cipher when
// property Protection is set to a other RO_Cipher :-)
TPAction = (paEncode, paDecode, paScramble, paCalc, paWipe);
TPActions = set of TPAction;
{$IFDEF VER_D3H}
TROProtection = class(TInterfacedObject)
private
{$ELSE}
TROProtection = class(TObject)
private
FRefCount: Integer;
{$ENDIF}
FProtection: TROProtection;
FActions: TPActions;
function GetProtection: TROProtection;
procedure SetProtection(Value: TROProtection);
protected
procedure CodeInit(Action: TPAction); virtual;
procedure CodeDone(Action: TPAction); virtual;
procedure CodeBuf(var Buffer; const BufferSize: Integer; Action: TPAction); virtual;
public
constructor Create(AProtection: TROProtection);
destructor Destroy; override;
class function Identity: Word;
function Release: Integer;
function AddRef: Integer;
procedure CodeStream(Source, Dest: TStream; DataSize: Integer; Action: TPAction); virtual;
procedure CodeFile(const Source, Dest: String; Action: TPAction); virtual;
function CodeString(const Source: String; Action: TPAction; Format: Integer): String; virtual;
function CodeBuffer(var Buffer; BufferSize: Integer; Action: TPAction): Integer; virtual;
// Protection Object, to cascade more Protection
property Protection: TROProtection read GetProtection write SetProtection;
property Actions: TPActions read FActions write FActions default [paEncode..paWipe];
{$IFNDEF VER_D3H}
property RefCount: Integer read FRefCount;
{$ENDIF}
end;
// String converting
TROStringFormatClass = class of TROStringFormat;
TROStringFormat = class(TObject) // for binary one to one convert = fmtCOPY
public
class function ToStr(Value: PChar; Len: Integer): String; virtual;
class function StrTo(Value: PChar; Len: Integer): String; virtual;
class function Name: String; virtual;
class function Format: Integer; virtual;
class function IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean; virtual;
end;
TROStringFormat_HEX = class(TROStringFormat) // Hexadecimal = fmtHEX
public
class function ToStr(Value: PChar; Len: Integer): String; override;
class function StrTo(Value: PChar; Len: Integer): String; override;
class function Name: String; override;
class function Format: Integer; override;
class function IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean; override;
class function CharTable: PChar; virtual;
end;
TROStringFormat_HEXL = class(TROStringFormat_HEX) // Hexadecimal lowercase = fmtHEXL
public
class function Name: String; override;
class function Format: Integer; override;
class function CharTable: PChar; override;
end;
TROStringFormat_MIME64 = class(TROStringFormat_HEX) // MIME Base 64 = fmtMIME64
public
class function ToStr(Value: PChar; Len: Integer): String; override;
class function StrTo(Value: PChar; Len: Integer): String; override;
class function Name: String; override;
class function Format: Integer; override;
class function CharTable: PChar; override;
end;
TROStringFormat_UU = class(TROStringFormat) // UU Encode = fmtUU
public
class function ToStr(Value: PChar; Len: Integer): String; override;
class function StrTo(Value: PChar; Len: Integer): String; override;
class function Name: String; override;
class function Format: Integer; override;
class function IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean; override;
class function CharTable: PChar; virtual;
end;
TROStringFormat_XX = class(TROStringFormat_UU) // XX Encode = fmtXX
public
class function Name: String; override;
class function Format: Integer; override;
class function CharTable: PChar; override;
end;
{Progress (gauge) for RO_Hash and RO_Cipher}
TProgressEvent = procedure(Sender: TObject; Current, Maximal: Integer) of Object;
//calculate CRCR16/CRC32 Checksum, CRC is default $FFFFFFFF,
//after calc you must inverse Result with NOT
function CRC16(CRC: Word; Data: Pointer; DataSize: LongWord): Word;
function CRC32(CRC: LongWord; Data: Pointer; DataSize: LongWord): LongWord;
// the basicly used TestVector for all RO_Hash/RO_Cipher classes
// used for SelfTest, random Data, don't modify
function GetTestVector: PChar; register;
// String/Format routines
// convert any String to Format
function StrToFormat(Value: PChar; Len, Format: Integer): String;
// convert any Format to String
function FormatToStr(Value: PChar; Len, Format: Integer): String;
// convert any Format to Format
function ConvertFormat(Value: PChar; Len, FromFormat, ToFormat: Integer): String;
// Check is String convertable to Format
function IsValidString(Value: PChar; Len, Format: Integer): Boolean;
// Check is Format an valid Format
function IsValidFormat(Value: PChar; Len, Format: Integer): Boolean;
// register a new Format
procedure RegisterStringFormats(const StringFormats: array of TROStringFormatClass);
// give all registered Formats in Strings
procedure GetStringFormats(Strings: TStrings);
// the Default, = fmtMIME64
function DefaultStringFormat: Integer;
// set the Default
procedure SetDefaultStringFormat(Format: Integer);
// give StringFormatClass from Format
function StringFormat(Format: Integer): TROStringFormatClass;
// insert #13#10 Chars in Blocks from BlockSize
function InsertCR(const Value: String; BlockSize: Integer): String;
// delete all #13 and #10 Chars
function DeleteCR(const Value: String): String;
// format any String to a Block
function InsertBlocks(const Value, BlockStart, BlockEnd: String; BlockSize: Integer): String;
// remove any Block format
function RemoveBlocks(const Value, BlockStart, BlockEnd: String): String;
// give back a shorter Name, i.E. TROHash_MD4 -> "MD4" or TROCipher_Blowfish -> "Blowfish"
function GetShortClassName(Value: TClass): String;
// Result := Value shl Shift or Value shr (32 - Shift)
function ROL(Value: LongWord; Shift: Integer): LongWord;
// Result := ROL(Value, Shift) + Add
function ROLADD(Value, Add: LongWord; Shift: Integer): LongWord;
// Result := ROL(Value, Shift) - Sub
function ROLSUB(Value, Sub: LongWord; Shift: Integer): LongWord;
// Result := Value shr Shift or Value shl (32 - Shift)
function ROR(Value: LongWord; Shift: Integer): LongWord;
// Result := ROR(Value, Shift) + Add
function RORADD(Value, Add: LongWord; Shift: Integer): LongWord;
// Result := ROR(Value, Shift) - Sub
function RORSUB(Value, Sub: LongWord; Shift: Integer): LongWord;
// Reverse the Bitorder from Value
function SwapBits(Value: LongWord): LongWord;
// Index of Least Significant Bit from Value
function LSBit(Value: Integer): Integer;
// Index of Most Significant Bit from Value
function MSBit(Value: Integer): Integer;
// Check iff only One Bit is set and give back the Index
function OneBit(Value: Integer): Integer;
// Compare Memory, D2 have no CompareMem, Result can be -1, 0, 1
function MemCompare(P1, P2: Pointer; Size: Integer): Integer;
// XOR's Buffers I1 and I2 Size Bytes to Dest
procedure XORBuffers(I1, I2: Pointer; Size: Integer; Dest: Pointer);
// Processor Type
function CPUType: Integer; {3 = 386, 4 = 486, 5 = Pentium, 6 > Pentium i.E. PII}
// call a installed Progress Event
procedure DoProgress(Sender: TObject; Current, Maximal: Integer);
// saver Test
function IsObject(AObject: Pointer; AClass: TClass): Boolean;
// Time Seed produced from GetSystemTime and QueryPerformanceCounter
function RndTimeSeed: Integer;
// XOR Buffer Size Bytes with Seed Randoms,
// the initial State from Buffer have effect on the Output
function RndXORBuffer(Seed: Integer; var Buffer; Size: Integer): Integer;
// encapsulate QueryPerformanceCounter/Frequency
{$IFNDEF DELPHI10UP}
function PerfCounter: Comp;
function PerfFreq: Comp;
{$ENDIF}
const
InitTestIsOk : Boolean = False;
IdentityBase : Word = $1234;
{this is set to SwapInt for <= 386 and BSwapInt >= 486 CPU, don't modify}
SwapInteger : function(Value: LongWord): LongWord; register = nil;
{Count of Integers Buffer}
SwapIntegerBuffer : procedure(Source, Dest: Pointer; Count: Integer); register = nil;
{Progress callback function, set this to your Progresscallback}
Progress: TProgressEvent = nil;
implementation
uses Windows, uRODECConst;
const
FCPUType : Integer = 0;
FStrFMTs : TList = nil; // registered Stringformats
FStrFMT : Integer = fmtMIME64; // Default Stringformat
function PerfCounter: Comp;
begin
{$IFDEF VER_D4H}
if not QueryPerformanceCounter(TULargeInteger(Result).QuadPart) then
{$ELSE}
if not QueryPerformanceCounter(TLargeInteger(Result)) then
{$ENDIF}
Result := GetTickCount;
end;
function PerfFreq: Comp;
begin
{$IFDEF VER_D4H}
if not QueryPerformanceFrequency(TULargeInteger(Result).QuadPart) then
{$ELSE}
if not QueryPerformanceFrequency(TLargeInteger(Result)) then
{$ENDIF}
Result := 1000;
end;
function DefaultStringFormat: Integer;
begin
Result := FStrFMT;
end;
procedure SetDefaultStringFormat(Format: Integer);
begin
if (Format = fmtDEFAULT) or (StringFormat(Format) = nil) then FStrFMT := fmtMIME64
else FStrFMT := Format;
end;
// TROProtection Class
function TROProtection.GetProtection: TROProtection;
begin
if (FProtection <> nil) and not IsObject(FProtection, TROProtection) then FProtection := nil;
Result := FProtection;
end;
procedure TROProtection.SetProtection(Value: TROProtection);
function CheckProtection(P: TROProtection): Boolean;
begin
Result := True;
if IsObject(P, TROProtection) then
if P = Self then Result := False
else Result := CheckProtection(P.FProtection)
end;
begin
if Value <> FProtection then
if CheckProtection(Value) then
begin
FProtection.Release;
FProtection := Value;
FProtection.AddRef;
end else raise EROProtection.Create(sProtectionCircular)
end;
procedure TROProtection.CodeInit(Action: TPAction);
begin
if Protection <> nil then Protection.CodeInit(Action);
end;
procedure TROProtection.CodeDone(Action: TPAction);
begin
if Protection <> nil then Protection.CodeDone(Action);
end;
procedure TROProtection.CodeBuf(var Buffer; const BufferSize: Integer; Action: TPAction);
begin
if Protection <> nil then Protection.CodeBuf(Buffer, BufferSize, Action);
end;
function TROProtection.Release: Integer;
begin
if IsObject(Self, TROProtection) then
begin
{$IFDEF VER_D3H}
Result := IUnknown(Self)._Release;
{$ELSE}
Dec(FRefCount);
Result := FRefCount;
if FRefCount = 0 then Destroy;
{$ENDIF}
end else Result := 0;
end;
function TROProtection.AddRef: Integer;
begin
if IsObject(Self, TROProtection) then
begin
{$IFDEF VER_D3H}
Result := IUnknown(Self)._AddRef;
{$ELSE}
Inc(FRefCount);
Result := FRefCount;
{$ENDIF}
end else Result := 0;
end;
procedure TROProtection.CodeStream(Source, Dest: TStream; DataSize: Integer; Action: TPAction);
const
maxBufSize = 1024 * 4;
var
Buf: PChar;
SPos: Integer;
DPos: Integer;
Len: Integer;
Size: Integer;
begin
if Source = nil then Exit;
if Dest = nil then Dest := Source;
if DataSize < 0 then
begin
DataSize := Source.Size;
Source.Position := 0;
end;
CodeInit(Action);
Buf := nil;
Size := DataSize;
DoProgress(Self, 0, Size);
try
Buf := AllocMem(maxBufSize);
DPos := Dest.Position;
SPos := Source.Position;
if Action = paCalc then
begin
while DataSize > 0 do
begin
Len := DataSize;
if Len > maxBufSize then Len := maxBufSize;
Len := Source.Read(Buf^, Len);
if Len <= 0 then Break;
CodeBuf(Buf^, Len, paCalc);
Dec(DataSize, Len);
DoProgress(Self, Size - DataSize, Size);
end;
end else
begin
while DataSize > 0 do
begin
Source.Position := SPos;
Len := DataSize;
if Len > maxBufSize then Len := maxBufSize;
Len := Source.Read(Buf^, Len);
SPos := Source.Position;
if Len <= 0 then Break;
CodeBuf(Buf^, Len, Action);
Dest.Position := DPos;
Dest.Write(Buf^, Len);
DPos := Dest.Position;
Dec(DataSize, Len);
DoProgress(Self, Size - DataSize, Size);
end;
end;
finally
DoProgress(Self, 0, 0);
ReallocMem(Buf, 0);
CodeDone(Action);
end;
end;
procedure TROProtection.CodeFile(const Source, Dest: String; Action: TPAction);
var
S,D: TFileStream;
begin
S := nil;
D := nil;
try
if (AnsiCompareText(Source, Dest) <> 0) and ((Trim(Dest) <> '') or (Action = paCalc)) then
begin
S := TFileStream.Create(Source, fmOpenRead or fmShareDenyNone);
if Action = paCalc then D := S
else D := TFileStream.Create(Dest, fmCreate);
end else
begin
S := TFileStream.Create(Source, fmOpenReadWrite);
D := S;
end;
CodeStream(S, D, S.Size, Action);
finally
S.Free;
if S <> D then
begin
{$IFDEF VER_D3H}
D.Size := D.Position;
{$ENDIF}
D.Free;
end;
end;
end;
function TROProtection.CodeBuffer(var Buffer; BufferSize: Integer; Action: TPAction): Integer;
begin
Result := BufferSize;
CodeInit(Action);
try
CodeBuf(Buffer, BufferSize, Action);
finally
CodeDone(Action);
end;
end;
function TROProtection.CodeString(const Source: String; Action: TPAction; Format: Integer): String;
var
M: TMemoryStream;
begin
Result := '';
if Length(Source) <= 0 then Exit;
M := TMemoryStream.Create;
try
if Action <> paDecode then Result := Source
else Result := FormatToStr(PChar(Source), Length(Source), Format);
M.Write(PChar(Result)^, Length(Result));
M.Position := 0;
CodeStream(M, M, M.Size, Action);
if Action = paDecode then
begin
SetLength(Result, M.Size);
Move(M.Memory^, PChar(Result)^, M.Size);
end else
Result := StrToFormat(M.Memory, M.Size, Format);
finally
M.Free;
end;
end;
constructor TROProtection.Create(AProtection: TROProtection);
begin
inherited Create;
Protection := AProtection;
FActions := [paEncode..paWipe];
end;
destructor TROProtection.Destroy;
begin
Protection := nil;
inherited Destroy;
end;
class function TROProtection.Identity: Word;
var
S: String;
begin
S := ClassName;
Result := not CRC16(IdentityBase, PChar(S), Length(S));
end;
class function TROStringFormat.ToStr(Value: PChar; Len: Integer): String;
begin
SetLength(Result, Len);
Move(Value^, PChar(Result)^, Len);
end;
class function TROStringFormat.StrTo(Value: PChar; Len: Integer): String;
begin
SetLength(Result, Len);
Move(Value^, PChar(Result)^, Len);
end;
class function TROStringFormat.Name: String;
begin
if Self = TROStringFormat then Result := sFMT_COPY
else Result := GetShortClassName(Self);
end;
class function TROStringFormat.Format: Integer;
begin
Result := fmtCOPY;
end;
class function TROStringFormat.IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean;
begin
Result := True;
end;
function TableFind(Value: Char; Table: PChar; Len: Integer): Integer; assembler;
asm // Utility for TStringFormat_XXXXX
PUSH EDI
MOV EDI,EDX
REPNE SCASB
MOV EAX,0
JNE @@1
MOV EAX,EDI
SUB EAX,EDX
@@1: DEC EAX
POP EDI
end;
class function TROStringFormat_HEX.ToStr(Value: PChar; Len: Integer): String;
var
D: PByte;
T: PChar;
I,P: Integer;
HasIdent: Boolean;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len div 2 +1);
T := CharTable;
D := PByte(Result);
I := 0;
HasIdent := False;
while Len > 0 do
begin
P := TableFind(UpCase(Value^), T, 18);
Inc(Value);
if P >= 0 then
if P > 16 then
begin
if not HasIdent then
begin
HasIdent := True;
I := 0;
D := PByte(Result);
end;
end else
begin
if Odd(I) then
begin
D^ := D^ or P;
Inc(D);
end else D^ := P shl 4;
Inc(I);
end;
Dec(Len);
end;
SetLength(Result, PChar(D) - PChar(Result));
end;
class function TROStringFormat_HEX.StrTo(Value: PChar; Len: Integer): String;
var
D,T: PChar;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len * 2);
T := CharTable;
D := PChar(Result);
while Len > 0 do
begin
D[0] := T[Byte(Value^) shr 4];
D[1] := T[Byte(Value^) and $F];
Inc(D, 2);
Inc(Value);
Dec(Len);
end;
end;
class function TROStringFormat_HEX.IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean;
var
T: PChar;
L: Integer;
begin
Result := not ToStr;
if not Result then
begin
T := CharTable;
L := StrLen(T);
while Len > 0 do
if TableFind(Value^, T, L) >= 0 then
begin
Dec(Len);
Inc(Value);
end else Exit;
end;
Result := True;
end;
class function TROStringFormat_HEX.Name: String;
begin
Result := sFMT_HEX;
end;
class function TROStringFormat_HEX.Format: Integer;
begin
Result := fmtHEX;
end;
class function TROStringFormat_HEX.CharTable: PChar; assembler;
asm
MOV EAX,OFFSET @@1
RET
@@1: DB '0123456789ABCDEF' // Table must be >= 18 Chars
DB 'X$ abcdefhHx()[]{},;:-_/\*+"''',9,10,13,0
end;
class function TROStringFormat_HEXL.Name: String;
begin
Result := sFMT_HEXL;
end;
class function TROStringFormat_HEXL.Format: Integer;
begin
Result := fmtHEXL;
end;
class function TROStringFormat_HEXL.CharTable: PChar;
asm
MOV EAX,OFFSET @@1
RET
@@1: DB '0123456789abcdef' // Table must be >= 18 Chars
DB 'X$ ABCDEFhHx()[]{},;:-_/\*+"''',9,10,13,0
end;
class function TROStringFormat_MIME64.ToStr(Value: PChar; Len: Integer): String;
var
B: Cardinal;
J,I: Integer;
S,D,L,T: PChar;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := Length(Value);
if Len = 0 then Exit;
SetLength(Result, Len);
Move(PChar(Value)^, PChar(Result)^, Len);
T := CharTable;
while Len mod 4 <> 0 do
begin
Result := Result + T[64];
Inc(Len);
end;
D := PChar(Result);
S := D;
L := S + Len;
Len := Len * 3 div 4;
while Len > 0 do
begin
B := 0;
J := 4;
while (J > 0) and (S <= L) do
begin
I := TableFind(S^, T, 65);
if I >= 0 then
begin
B := B shl 6;
if I >= 64 then Dec(Len) else B := B or Byte(I);
Dec(J);
end;
Inc(S);
end;
J := 2;
repeat
D[J] := Char(B);
B := B shr 8;
Dec(J);
until J < 0;
if Len > 3 then Inc(D, 3) else Inc(D, Len);
Dec(Len, 3);
end;
SetLength(Result, D - PChar(Result));
end;
class function TROStringFormat_MIME64.StrTo(Value: PChar; Len: Integer): String;
var
B: Cardinal;
I: Integer;
D,T: PChar;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len * 4 div 3 + 4);
D := PChar(Result);
T := CharTable;
while Len > 0 do
begin
B := 0;
for I := 0 to 2 do
begin
B := B shl 8;
if Len > 0 then
begin
B := B or Byte(Value^);
Inc(Value);
end;
Dec(Len);
end;
for I := 3 downto 0 do
begin
if Len < 0 then
begin
D[I] := T[64];
Inc(Len);
end else D[I] := T[B and $3F];
B := B shr 6;
end;
Inc(D, 4);
end;
SetLength(Result, D - PChar(Result));
end;
class function TROStringFormat_MIME64.Name: String;
begin
Result := sFMT_MIME64;
end;
class function TROStringFormat_MIME64.Format: Integer;
begin
Result := fmtMIME64;
end;
class function TROStringFormat_MIME64.CharTable: PChar; assembler;
asm
MOV EAX,OFFSET @@1
RET // must be >= 65 Chars
@@1: DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
DB ' $()[]{},;:-_\*"''',9,10,13,0
end;
class function TROStringFormat_UU.ToStr(Value: PChar; Len: Integer): String;
var
T,D,L: PChar;
I,E: Integer;
B: Cardinal;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len);
L := Value + Len;
D := PChar(Result);
T := CharTable;
repeat
Len := TableFind(Value^, T, 64);
if (Len < 0) or (Len > 45) then
raise EROStringFormat.CreateFMT(sInvalidStringFormat, [Name]);
Inc(Value);
while Len > 0 do
begin
B := 0;
I := 4;
while (I > 0) and (Value <= L) do
begin
E := TableFind(Value^, T, 64);
if E >= 0 then
begin
B := B shl 6 or Byte(E);
Dec(I);
end;
Inc(Value);
end;
I := 2;
repeat
D[I] := Char(B);
B := B shr 8;
Dec(I);
until I < 0;
if Len > 3 then Inc(D, 3) else Inc(D, Len);
Dec(Len, 3);
end;
until Value >= L;
SetLength(Result, D - PChar(Result));
end;
class function TROStringFormat_UU.StrTo(Value: PChar; Len: Integer): String;
var
T,D: PChar;
L,I: Integer;
B: Cardinal;
begin
Result := '';
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len * 4 div 3 + Len div 45 + 10);
D := PChar(Result);
T := CharTable;
while Len > 0 do
begin
L := Len;
if L > 45 then L := 45;
Dec(Len, L);
D^ := T[L];
while L > 0 do
begin
B := 0;
for I := 0 to 2 do
begin
B := B shl 8;
if L > 0 then
begin
B := B or Byte(Value^);
Inc(Value);
end;
Dec(L);
end;
for I := 4 downto 1 do
begin
D[I] := T[B and $3F];
B := B shr 6;
end;
Inc(D, 4);
end;
Inc(D);
end;
SetLength(Result, D - PChar(Result));
end;
class function TROStringFormat_UU.Name: String;
begin
Result := sFMT_UU;
end;
class function TROStringFormat_UU.Format: Integer;
begin
Result := fmtUU;
end;
class function TROStringFormat_UU.IsValid(Value: PChar; Len: Integer; ToStr: Boolean): Boolean;
var
T: PChar;
L,I,P: Integer;
begin
Result := not ToStr;
if not Result then
begin
T := CharTable;
L := StrLen(T);
P := 0;
while Len > 0 do
begin
I := TableFind(Value^, T, L);
if I >= 0 then
begin
Dec(Len);
Inc(Value);
if P = 0 then
begin
if I > 45 then Exit;
P := (I * 4 + 2) div 3;
end else
if I < 64 then Dec(P);
end else Exit;
end;
if P <> 0 then Exit;
end;
Result := True;
end;
class function TROStringFormat_UU.CharTable: PChar;
asm
MOV EAX,OFFSET @@1
RET // must be >= 64 Chars
@@1: DB '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
DB ' ',9,10,13,0
end;
class function TROStringFormat_XX.Name: String;
begin
Result := sFMT_XX;
end;
class function TROStringFormat_XX.Format: Integer;
begin
Result := fmtXX;
end;
class function TROStringFormat_XX.CharTable: PChar;
asm
MOV EAX,OFFSET @@1
RET
@@1: DB '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
DB ' "()[]''',9,10,13,0
end;
function CPUType: Integer;
begin
Result := FCPUType;
end;
function IsObject(AObject: Pointer; AClass: TClass): Boolean;
var
E: Pointer;
begin
Result := False;
if AObject = nil then Exit;
E := ExceptionClass;
ExceptionClass := nil;
try
if TObject(AObject) is AClass then Result := True;
except
end;
ExceptionClass := E;
end;
function ROL(Value: LongWord; Shift: Integer): LongWord; assembler;
asm
MOV ECX,EDX
ROL EAX,CL
end;
function ROLADD(Value, Add: LongWord; Shift: Integer): LongWord; assembler;
asm
ROL EAX,CL
ADD EAX,EDX
end;
function ROLSUB(Value, Sub: LongWord; Shift: Integer): LongWord; assembler;
asm
ROL EAX,CL
SUB EAX,EDX
end;
function ROR(Value: LongWord; Shift: Integer): LongWord; assembler;
asm
MOV ECX,EDX
ROR EAX,CL
end;
function RORADD(Value, Add: LongWord; Shift: Integer): LongWord; assembler;
asm
ROR EAX,CL
ADD EAX,EDX
end;
function RORSUB(Value, Sub: LongWord; Shift: Integer): LongWord; assembler;
asm
ROR EAX,CL
SUB EAX,EDX
end;
{swap 4 Bytes Intel, Little/Big Endian Conversion}
function SwapInt(Value: LongWord): LongWord; assembler; register;
asm
XCHG AH,AL
ROL EAX,16
XCHG AH,AL
end;
function BSwapInt(Value: LongWord): LongWord; assembler; register;
asm
BSWAP EAX
end;
procedure SwapIntBuf(Source,Dest: Pointer; Count: Integer); assembler; register;
asm
TEST ECX,ECX
JLE @Exit
PUSH EBX
SUB EAX,4
SUB EDX,4
@@1: MOV EBX,[EAX + ECX * 4]
XCHG BL,BH
ROL EBX,16
XCHG BL,BH
MOV [EDX + ECX * 4],EBX
DEC ECX
JNZ @@1
POP EBX
@Exit:
end;
procedure BSwapIntBuf(Source, Dest: Pointer; Count: Integer); assembler; register;
asm
TEST ECX,ECX
JLE @Exit
PUSH EBX
SUB EAX,4
SUB EDX,4
@@1: MOV EBX,[EAX + ECX * 4]
BSWAP EBX
MOV [EDX + ECX * 4],EBX
DEC ECX
JNZ @@1
POP EBX
@Exit:
end;
{reverse the bit order from a integer}
function SwapBits(Value: LongWord): LongWord;
asm
CMP FCPUType,3
JLE @@1
BSWAP EAX
JMP @@2
@@1: XCHG AH,AL
ROL EAX,16
XCHG AH,AL
@@2: MOV EDX,EAX
AND EAX,0AAAAAAAAh
SHR EAX,1
AND EDX,055555555h
SHL EDX,1
OR EAX,EDX
MOV EDX,EAX
AND EAX,0CCCCCCCCh
SHR EAX,2
AND EDX,033333333h
SHL EDX,2
OR EAX,EDX
MOV EDX,EAX
AND EAX,0F0F0F0F0h
SHR EAX,4
AND EDX,00F0F0F0Fh
SHL EDX,4
OR EAX,EDX
end;
function LSBit(Value: Integer): Integer; assembler;
asm
BSF EAX,EAX
end;
function MSBit(Value: Integer): Integer; assembler;
asm
BSR EAX,EAX
end;
function OneBit(Value: Integer): Integer; assembler;
asm
MOV ECX,EAX
MOV EDX,EAX
BSF EDX,EDX
JZ @@1
BSR ECX,ECX
CMP ECX,EDX
JNE @@1
MOV EAX,EDX
RET
@@1: XOR EAX,EAX
end;
function MemCompare(P1, P2: Pointer; Size: Integer): Integer; assembler; register;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
XOR EAX,EAX
REPE CMPSB
JE @@1
MOVZX EAX,BYTE PTR [ESI-1]
MOVZX EDX,BYTE PTR [EDI-1]
SUB EAX,EDX
@@1: POP EDI
POP ESI
end;
procedure XORBuffers(I1, I2: Pointer; Size: Integer; Dest: Pointer); assembler;
asm
AND ECX,ECX
JZ @@5
PUSH ESI
PUSH EDI
MOV ESI,EAX
MOV EDI,Dest
@@1: TEST ECX,3
JNZ @@3
@@2: SUB ECX,4
JL @@4
MOV EAX,[ESI + ECX]
XOR EAX,[EDX + ECX]
MOV [EDI + ECX],EAX
JMP @@2
@@3: DEC ECX
MOV AL,[ESI + ECX]
XOR AL,[EDX + ECX]
MOV [EDI + ECX],AL
JMP @@1
@@4: POP EDI
POP ESI
@@5:
end;
procedure DoProgress(Sender: TObject; Current, Maximal: Integer);
begin
{saver access}
if (TMethod(Progress).Code <> nil) and
((TMethod(Progress).Data = nil) or
IsObject(TMethod(Progress).Data, TObject)) then
Progress(Sender, Current, Maximal);
end;
function StringFormat(Format: Integer): TROStringFormatClass;
var
I: Integer;
begin
if Format = fmtDefault then Format := DefaultStringFormat;
Result := nil;
if FStrFmts <> nil then
for I := 0 to FStrFMTs.Count-1 do
if TROStringFormatClass(FStrFmts[I]).Format = Format then
begin
Result := FStrFMTS[I];
Exit;
end;
end;
function StrToFormat(Value: PChar; Len, Format: Integer): String;
var
Fmt: TROStringFormatClass;
begin
Result := '';
if (Value = nil) or (Format = fmtNONE) then Exit;
if Len < 0 then Len := StrLen(Value);
if Len <= 0 then Exit;
Fmt := StringFormat(Format);
if Fmt <> nil then
if Fmt.IsValid(Value, Len, False) then Result := Fmt.StrTo(Value, Len)
else raise EROStringFormat.CreateFMT(sInvalidFormatString, [FMT.Name])
else raise EROStringFormat.CreateFMT(sStringFormatExists, [Format]);
end;
function FormatToStr(Value: PChar; Len, Format: Integer): String;
var
Fmt: TROStringFormatClass;
begin
Result := '';
if (Value = nil) or (Format = fmtNONE) then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
Fmt := StringFormat(Format);
if Fmt <> nil then
if Fmt.IsValid(Value, Len, True) then Result := Fmt.ToStr(Value, Len)
else raise EROStringFormat.CreateFMT(sInvalidStringFormat, [FMT.Name])
else raise EROStringFormat.CreateFMT(sStringFormatExists, [Format]);
end;
function ConvertFormat(Value: PChar; Len, FromFormat, ToFormat: Integer): String;
begin
Result := '';
if (FromFormat = fmtNONE) or (ToFormat = fmtNONE) then Exit;
if FromFormat <> ToFormat then
begin
Result := FormatToStr(Value, Len, FromFormat);
Result := StrToFormat(PChar(Result), Length(Result), ToFormat);
end else
begin
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
SetLength(Result, Len);
Move(Value^, PChar(Result)^, Len);
end;
end;
function IsValidFormat(Value: PChar; Len, Format: Integer): Boolean;
var
Fmt: TROStringFormatClass;
begin
Result := True;
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
Fmt := StringFormat(Format);
if Fmt = nil then Result := False
else Result := Fmt.IsValid(Value, Len, True);
end;
function IsValidString(Value: PChar; Len, Format: Integer): Boolean;
var
Fmt: TROStringFormatClass;
begin
Result := True;
if Value = nil then Exit;
if Len < 0 then Len := StrLen(Value);
if Len = 0 then Exit;
Fmt := StringFormat(Format);
if Fmt = nil then Result := False
else Result := Fmt.IsValid(Value, Len, False);
end;
procedure RegisterStringFormats(const StringFormats: array of TROStringFormatClass);
var
I,J: Integer;
FMT: TROStringFormatClass;
begin
if FStrFMTs = nil then FStrFMTs := TList.Create;
for I := Low(StringFormats) to High(StringFormats) do
if (StringFormats[I] <> nil) and
(StringFormats[I].Format <> fmtDEFAULT) then
begin
FMT := StringFormat(StringFormats[I].Format);
if FMT <> nil then
begin
J := FStrFMTs.IndexOf(FMT);
FStrFMTs[J] := StringFormats[I];
end else FStrFMTs.Add(StringFormats[I]);
end;
end;
procedure GetStringFormats(Strings: TStrings);
var
I: Integer;
begin
if IsObject(Strings, TStrings) and (FStrFMTs <> nil) then
for I := 0 to FStrFMTs.Count-1 do
Strings.AddObject(TROStringFormatClass(FStrFMTs[I]).Name, FStrFMTs[I]);
end;
function InsertCR(const Value: String; BlockSize: Integer): String;
var
I: Integer;
S,D: PChar;
begin
if (BlockSize <= 0) or (Length(Value) <= BlockSize) then
begin
Result := Value;
Exit;
end;
I := Length(Value);
SetLength(Result, I + I * 2 div BlockSize + 2);
S := PChar(Value);
D := PChar(Result);
repeat
Move(S^, D^, BlockSize);
Inc(S, BlockSize);
Inc(D, BlockSize);
D^ := #13; Inc(D);
D^ := #10; Inc(D);
Dec(I, BlockSize);
until I < BlockSize;
Move(S^, D^, I);
Inc(D, I);
SetLength(Result, D - PChar(Result));
end;
function DeleteCR(const Value: String): String;
var
S,D: PChar;
I: Integer;
begin
I := Length(Value);
SetLength(Result, I);
D := PChar(Result);
S := PChar(Value);
while I > 0 do
begin
if (S^ <> #10) and (S^ <> #13) then
begin
D^ := S^;
Inc(D);
end;
Inc(S);
Dec(I);
end;
SetLength(Result, D - PChar(Result));
end;
function InsertBlocks(const Value, BlockStart, BlockEnd: String; BlockSize: Integer): String;
var
I,LS,LE: Integer;
D,S: PChar;
begin
if (BlockSize <= 0) or (Length(Value) <= BlockSize) then
begin
Result := Value;
Exit;
end;
I := Length(Value);
LS := Length(BlockStart);
LE := Length(BlockEnd);
SetLength(Result, I + (I div BlockSize + 1) * (LS + LE));
S := PChar(Value);
D := PChar(Result);
repeat
Move(PChar(BlockStart)^, D^, LS); Inc(D, LS);
Move(S^, D^, BlockSize); Inc(D, BlockSize);
Move(PChar(BlockEnd)^, D^, LE); Inc(D, LE);
Dec(I, BlockSize);
Inc(S, BlockSize);
until I < BlockSize;
if I > 0 then
begin
Move(PChar(BlockStart)^, D^, LS); Inc(D, LS);
Move(S^, D^, I); Inc(D, I);
Move(PChar(BlockEnd)^, D^, LE); Inc(D, LE);
end;
SetLength(Result, D - PChar(Result));
end;
function RemoveBlocks(const Value, BlockStart, BlockEnd: String): String;
var
LS,LE: Integer;
S,D,L,K: PChar;
begin
SetLength(Result, Length(Value));
LS := Length(BlockStart);
LE := Length(BlockEnd);
D := PChar(Result);
S := PChar(Value);
L := S + Length(Value);
repeat
if S > L then Break;
if LS > 0 then
begin
S := StrPos(S, PChar(BlockStart));
if S = nil then Break;
Inc(S, LS);
if S > L then Break;
end;
K := StrPos(S, PChar(BlockEnd));
if K = nil then K := L;
Move(S^, D^, K - S);
Inc(D, K - S);
S := K + LE;
until S >= L;
SetLength(Result, D - PChar(Result));
end;
function GetShortClassName(Value: TClass): String;
var
I: Integer;
begin
Result := '';
if Value = nil then Exit;
Result := Value.ClassName;
I := Pos('_', Result);
if I > 0 then Delete(Result, 1, I);
end;
function RndXORBuffer(Seed: Integer; var Buffer; Size: Integer): Integer; assembler;
asm
AND EDX,EDX
JZ @@2
AND ECX,ECX
JLE @@2
PUSH EBX
@@1: XOR AL,[EDX]
IMUL EAX,EAX,134775813
INC EAX
MOV EBX,EAX
SHR EBX,24
MOV [EDX],BL
INC EDX
DEC ECX
JNZ @@1
POP EBX
@@2:
end;
// use Systemtime and XOR's with Performancecounter
function RndTimeSeed: Integer; assembler;
var
SysTime: record
Year: Word;
Month: Word;
DayOfWeek: Word;
Day: Word;
Hour: Word;
Minute: Word;
Second: Word;
MilliSeconds: Word;
Reserved: array [0..7] of Byte;
end;
Counter: record
Lo,Hi: Integer;
end;
asm
LEA EAX,SysTime
PUSH EAX
CALL GetSystemTime
MOVZX EAX,Word Ptr SysTime.Hour
IMUL EAX,60
ADD AX,SysTime.Minute
IMUL EAX,60
MOVZX EDX,Word Ptr SysTime.Second
ADD EAX,EDX
IMUL EAX,1000
MOV DX,SysTime.MilliSeconds
ADD EAX,EDX
PUSH EAX
LEA EAX,Counter
PUSH EAX
CALL QueryPerformanceCounter
POP EAX
XOR EAX,Counter.Lo
XOR EAX,Counter.Hi
end;
function CRC16(CRC: Word; Data: Pointer; DataSize: LongWord): Word; assembler;
asm
AND EDX,EDX
JZ @Exit
AND ECX,ECX
JLE @Exit
PUSH EBX
PUSH EDI
XOR EBX,EBX
LEA EDI,CS:[OFFSET @CRC16]
@Start: MOV BL,[EDX]
XOR BL,AL
SHR AX,8
XOR AX,[EDI + EBX * 2]
INC EDX
DEC ECX
JNZ @Start
POP EDI
POP EBX
@Exit: RET
NOP
@CRC16: DW 00000h, 0C0C1h, 0C181h, 00140h, 0C301h, 003C0h, 00280h, 0C241h
DW 0C601h, 006C0h, 00780h, 0C741h, 00500h, 0C5C1h, 0C481h, 00440h
DW 0CC01h, 00CC0h, 00D80h, 0CD41h, 00F00h, 0CFC1h, 0CE81h, 00E40h
DW 00A00h, 0CAC1h, 0CB81h, 00B40h, 0C901h, 009C0h, 00880h, 0C841h
DW 0D801h, 018C0h, 01980h, 0D941h, 01B00h, 0DBC1h, 0DA81h, 01A40h
DW 01E00h, 0DEC1h, 0DF81h, 01F40h, 0DD01h, 01DC0h, 01C80h, 0DC41h
DW 01400h, 0D4C1h, 0D581h, 01540h, 0D701h, 017C0h, 01680h, 0D641h
DW 0D201h, 012C0h, 01380h, 0D341h, 01100h, 0D1C1h, 0D081h, 01040h
DW 0F001h, 030C0h, 03180h, 0F141h, 03300h, 0F3C1h, 0F281h, 03240h
DW 03600h, 0F6C1h, 0F781h, 03740h, 0F501h, 035C0h, 03480h, 0F441h
DW 03C00h, 0FCC1h, 0FD81h, 03D40h, 0FF01h, 03FC0h, 03E80h, 0FE41h
DW 0FA01h, 03AC0h, 03B80h, 0FB41h, 03900h, 0F9C1h, 0F881h, 03840h
DW 02800h, 0E8C1h, 0E981h, 02940h, 0EB01h, 02BC0h, 02A80h, 0EA41h
DW 0EE01h, 02EC0h, 02F80h, 0EF41h, 02D00h, 0EDC1h, 0EC81h, 02C40h
DW 0E401h, 024C0h, 02580h, 0E541h, 02700h, 0E7C1h, 0E681h, 02640h
DW 02200h, 0E2C1h, 0E381h, 02340h, 0E101h, 021C0h, 02080h, 0E041h
DW 0A001h, 060C0h, 06180h, 0A141h, 06300h, 0A3C1h, 0A281h, 06240h
DW 06600h, 0A6C1h, 0A781h, 06740h, 0A501h, 065C0h, 06480h, 0A441h
DW 06C00h, 0ACC1h, 0AD81h, 06D40h, 0AF01h, 06FC0h, 06E80h, 0AE41h
DW 0AA01h, 06AC0h, 06B80h, 0AB41h, 06900h, 0A9C1h, 0A881h, 06840h
DW 07800h, 0B8C1h, 0B981h, 07940h, 0BB01h, 07BC0h, 07A80h, 0BA41h
DW 0BE01h, 07EC0h, 07F80h, 0BF41h, 07D00h, 0BDC1h, 0BC81h, 07C40h
DW 0B401h, 074C0h, 07580h, 0B541h, 07700h, 0B7C1h, 0B681h, 07640h
DW 07200h, 0B2C1h, 0B381h, 07340h, 0B101h, 071C0h, 07080h, 0B041h
DW 05000h, 090C1h, 09181h, 05140h, 09301h, 053C0h, 05280h, 09241h
DW 09601h, 056C0h, 05780h, 09741h, 05500h, 095C1h, 09481h, 05440h
DW 09C01h, 05CC0h, 05D80h, 09D41h, 05F00h, 09FC1h, 09E81h, 05E40h
DW 05A00h, 09AC1h, 09B81h, 05B40h, 09901h, 059C0h, 05880h, 09841h
DW 08801h, 048C0h, 04980h, 08941h, 04B00h, 08BC1h, 08A81h, 04A40h
DW 04E00h, 08EC1h, 08F81h, 04F40h, 08D01h, 04DC0h, 04C80h, 08C41h
DW 04400h, 084C1h, 08581h, 04540h, 08701h, 047C0h, 04680h, 08641h
DW 08201h, 042C0h, 04380h, 08341h, 04100h, 081C1h, 08081h, 04040h
end;
function CRC32(CRC: LongWord; Data: Pointer; DataSize: LongWord): LongWord; assembler;
asm
AND EDX,EDX
JZ @Exit
AND ECX,ECX
JLE @Exit
PUSH EBX
PUSH EDI
XOR EBX,EBX
LEA EDI,CS:[OFFSET @CRC32]
@Start: MOV BL,AL
SHR EAX,8
XOR BL,[EDX]
XOR EAX,[EDI + EBX * 4]
INC EDX
DEC ECX
JNZ @Start
POP EDI
POP EBX
@Exit: RET
DB 0, 0, 0, 0, 0 // Align Table
@CRC32: DD 000000000h, 077073096h, 0EE0E612Ch, 0990951BAh
DD 0076DC419h, 0706AF48Fh, 0E963A535h, 09E6495A3h
DD 00EDB8832h, 079DCB8A4h, 0E0D5E91Eh, 097D2D988h
DD 009B64C2Bh, 07EB17CBDh, 0E7B82D07h, 090BF1D91h
DD 01DB71064h, 06AB020F2h, 0F3B97148h, 084BE41DEh
DD 01ADAD47Dh, 06DDDE4EBh, 0F4D4B551h, 083D385C7h
DD 0136C9856h, 0646BA8C0h, 0FD62F97Ah, 08A65C9ECh
DD 014015C4Fh, 063066CD9h, 0FA0F3D63h, 08D080DF5h
DD 03B6E20C8h, 04C69105Eh, 0D56041E4h, 0A2677172h
DD 03C03E4D1h, 04B04D447h, 0D20D85FDh, 0A50AB56Bh
DD 035B5A8FAh, 042B2986Ch, 0DBBBC9D6h, 0ACBCF940h
DD 032D86CE3h, 045DF5C75h, 0DCD60DCFh, 0ABD13D59h
DD 026D930ACh, 051DE003Ah, 0C8D75180h, 0BFD06116h
DD 021B4F4B5h, 056B3C423h, 0CFBA9599h, 0B8BDA50Fh
DD 02802B89Eh, 05F058808h, 0C60CD9B2h, 0B10BE924h
DD 02F6F7C87h, 058684C11h, 0C1611DABh, 0B6662D3Dh
DD 076DC4190h, 001DB7106h, 098D220BCh, 0EFD5102Ah
DD 071B18589h, 006B6B51Fh, 09FBFE4A5h, 0E8B8D433h
DD 07807C9A2h, 00F00F934h, 09609A88Eh, 0E10E9818h
DD 07F6A0DBBh, 0086D3D2Dh, 091646C97h, 0E6635C01h
DD 06B6B51F4h, 01C6C6162h, 0856530D8h, 0F262004Eh
DD 06C0695EDh, 01B01A57Bh, 08208F4C1h, 0F50FC457h
DD 065B0D9C6h, 012B7E950h, 08BBEB8EAh, 0FCB9887Ch
DD 062DD1DDFh, 015DA2D49h, 08CD37CF3h, 0FBD44C65h
DD 04DB26158h, 03AB551CEh, 0A3BC0074h, 0D4BB30E2h
DD 04ADFA541h, 03DD895D7h, 0A4D1C46Dh, 0D3D6F4FBh
DD 04369E96Ah, 0346ED9FCh, 0AD678846h, 0DA60B8D0h
DD 044042D73h, 033031DE5h, 0AA0A4C5Fh, 0DD0D7CC9h
DD 05005713Ch, 0270241AAh, 0BE0B1010h, 0C90C2086h
DD 05768B525h, 0206F85B3h, 0B966D409h, 0CE61E49Fh
DD 05EDEF90Eh, 029D9C998h, 0B0D09822h, 0C7D7A8B4h
DD 059B33D17h, 02EB40D81h, 0B7BD5C3Bh, 0C0BA6CADh
DD 0EDB88320h, 09ABFB3B6h, 003B6E20Ch, 074B1D29Ah
DD 0EAD54739h, 09DD277AFh, 004DB2615h, 073DC1683h
DD 0E3630B12h, 094643B84h, 00D6D6A3Eh, 07A6A5AA8h
DD 0E40ECF0Bh, 09309FF9Dh, 00A00AE27h, 07D079EB1h
DD 0F00F9344h, 08708A3D2h, 01E01F268h, 06906C2FEh
DD 0F762575Dh, 0806567CBh, 0196C3671h, 06E6B06E7h
DD 0FED41B76h, 089D32BE0h, 010DA7A5Ah, 067DD4ACCh
DD 0F9B9DF6Fh, 08EBEEFF9h, 017B7BE43h, 060B08ED5h
DD 0D6D6A3E8h, 0A1D1937Eh, 038D8C2C4h, 04FDFF252h
DD 0D1BB67F1h, 0A6BC5767h, 03FB506DDh, 048B2364Bh
DD 0D80D2BDAh, 0AF0A1B4Ch, 036034AF6h, 041047A60h
DD 0DF60EFC3h, 0A867DF55h, 0316E8EEFh, 04669BE79h
DD 0CB61B38Ch, 0BC66831Ah, 0256FD2A0h, 05268E236h
DD 0CC0C7795h, 0BB0B4703h, 0220216B9h, 05505262Fh
DD 0C5BA3BBEh, 0B2BD0B28h, 02BB45A92h, 05CB36A04h
DD 0C2D7FFA7h, 0B5D0CF31h, 02CD99E8Bh, 05BDEAE1Dh
DD 09B64C2B0h, 0EC63F226h, 0756AA39Ch, 0026D930Ah
DD 09C0906A9h, 0EB0E363Fh, 072076785h, 005005713h
DD 095BF4A82h, 0E2B87A14h, 07BB12BAEh, 00CB61B38h
DD 092D28E9Bh, 0E5D5BE0Dh, 07CDCEFB7h, 00BDBDF21h
DD 086D3D2D4h, 0F1D4E242h, 068DDB3F8h, 01FDA836Eh
DD 081BE16CDh, 0F6B9265Bh, 06FB077E1h, 018B74777h
DD 088085AE6h, 0FF0F6A70h, 066063BCAh, 011010B5Ch
DD 08F659EFFh, 0F862AE69h, 0616BFFD3h, 0166CCF45h
DD 0A00AE278h, 0D70DD2EEh, 04E048354h, 03903B3C2h
DD 0A7672661h, 0D06016F7h, 04969474Dh, 03E6E77DBh
DD 0AED16A4Ah, 0D9D65ADCh, 040DF0B66h, 037D83BF0h
DD 0A9BCAE53h, 0DEBB9EC5h, 047B2CF7Fh, 030B5FFE9h
DD 0BDBDF21Ch, 0CABAC28Ah, 053B39330h, 024B4A3A6h
DD 0BAD03605h, 0CDD70693h, 054DE5729h, 023D967BFh
DD 0B3667A2Eh, 0C4614AB8h, 05D681B02h, 02A6F2B94h
DD 0B40BBE37h, 0C30C8EA1h, 05A05DF1Bh, 02D02EF8Dh
DD 074726F50h, 0736E6F69h, 0706F4320h, 067697279h
DD 028207468h, 031202963h, 020393939h, 048207962h
DD 06E656761h, 064655220h, 06E616D64h, 06FBBA36Eh
end;
{a Random generated Testvector 256bit - 32 Bytes, it's used for Self Test}
function GetTestVector: PChar; assembler; register;
asm
MOV EAX,OFFSET @Vector
RET
@Vector: DB 030h,044h,0EDh,06Eh,045h,0A4h,096h,0F5h
DB 0F6h,035h,0A2h,0EBh,03Dh,01Ah,05Dh,0D6h
DB 0CBh,01Dh,009h,082h,02Dh,0BDh,0F5h,060h
DB 0C2h,0B8h,058h,0A1h,091h,0F9h,081h,0B1h
DB 000h,000h,000h,000h,000h,000h,000h,000h
end;
{get the CPU Type from your system}
function GetCPUType: Integer; assembler;
asm
PUSH EBX
PUSH ECX
PUSH EDX
MOV EBX,ESP
AND ESP,0FFFFFFFCh
PUSHFD
PUSHFD
POP EAX
MOV ECX,EAX
XOR EAX,40000h
PUSH EAX
POPFD
PUSHFD
POP EAX
XOR EAX,ECX
MOV EAX,3
JE @Exit
PUSHFD
POP EAX
MOV ECX,EAX
XOR EAX,200000h
PUSH EAX
POPFD
PUSHFD
POP EAX
XOR EAX,ECX
MOV EAX,4
JE @Exit
PUSH EBX
MOV EAX,1
DB 0Fh,0A2h //CPUID
MOV AL,AH
AND EAX,0Fh
POP EBX
@Exit: POPFD
MOV ESP,EBX
POP EDX
POP ECX
POP EBX
end;
procedure ModuleUnload(Instance: Longword);
var // automaticaly deregistration
I: Integer;
begin
if FStrFMTs <> nil then
for I := FStrFMTs.Count-1 downto 0 do
if FindClassHInstance(TClass(FStrFMTs[I])) = Instance then
FStrFMTs.Delete(I);
end;
initialization
AddModuleUnloadProc(ModuleUnload);
FCPUType := GetCPUType;
if FCPUType > 3 then
begin
SwapInteger := BSwapInt;
SwapIntegerBuffer := BSwapIntBuf;
end else
begin
SwapInteger := SwapInt;
SwapIntegerBuffer := SwapIntBuf;
end;
RegisterStringFormats([TROStringFormat, TROStringFormat_HEX, TROStringFormat_HEXL,
TROStringFormat_MIME64, TROStringFormat_UU, TROStringFormat_XX]);
{this calculate a Checksum (CRC32) over the function CRC32 and the TestVector,
if InitTestIsOk = False any modification from Testvector or CRC32() detected, :-) }
InitTestIsOk := CRC32(CRC32($29524828, PChar(@CRC32) + 41, 1076), GetTestVector, 32) = $848B5964;
finalization
RemoveModuleUnloadProc(ModuleUnload);
FStrFMTs.Free;
FStrFMTs := nil;
end.