- 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
1673 lines
48 KiB
ObjectPascal
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.
|