2079 lines
54 KiB
ObjectPascal
2079 lines
54 KiB
ObjectPascal
{ ****************************************************************************** }
|
|
{ * delphi:string fpc:AnsiString by QQ 600585@qq.com * }
|
|
{ * https://zpascal.net * }
|
|
{ * https://github.com/PassByYou888/zAI * }
|
|
{ * https://github.com/PassByYou888/ZServer4D * }
|
|
{ * https://github.com/PassByYou888/PascalString * }
|
|
{ * https://github.com/PassByYou888/zRasterization * }
|
|
{ * https://github.com/PassByYou888/CoreCipher * }
|
|
{ * https://github.com/PassByYou888/zSound * }
|
|
{ * https://github.com/PassByYou888/zChinese * }
|
|
{ * https://github.com/PassByYou888/zExpression * }
|
|
{ * https://github.com/PassByYou888/zGameWare * }
|
|
{ * https://github.com/PassByYou888/zAnalysis * }
|
|
{ * https://github.com/PassByYou888/FFMPEG-Header * }
|
|
{ * https://github.com/PassByYou888/zTranslate * }
|
|
{ * https://github.com/PassByYou888/InfiniteIoT * }
|
|
{ * https://github.com/PassByYou888/FastMD5 * }
|
|
{ ****************************************************************************** }
|
|
|
|
(*
|
|
update history
|
|
2017-11-26
|
|
fixed UnicodeString in FPC
|
|
*)
|
|
|
|
unit PascalStrings;
|
|
|
|
{$INCLUDE zDefine.inc}
|
|
|
|
interface
|
|
|
|
uses CoreClasses;
|
|
|
|
type
|
|
SystemChar = Char;
|
|
SystemString = string;
|
|
THash = Cardinal;
|
|
THash64 = UInt64;
|
|
PSystemString = ^SystemString;
|
|
PPascalString = ^TPascalString;
|
|
TArrayChar = array of SystemChar;
|
|
TOrdChar = (c0to9, c1to9, c0to32, c0to32no10, cLoAtoF, cHiAtoF, cLoAtoZ, cHiAtoZ, cHex, cAtoF, cAtoZ, cVisibled);
|
|
TOrdChars = set of TOrdChar;
|
|
|
|
TPascalString = record
|
|
private
|
|
function GetText: SystemString;
|
|
procedure SetText(const Value: SystemString);
|
|
function GetLen: Integer;
|
|
procedure SetLen(const Value: Integer);
|
|
function GetChars(index: Integer): SystemChar;
|
|
procedure SetChars(index: Integer; const Value: SystemChar);
|
|
function GetBytes: TBytes;
|
|
procedure SetBytes(const Value: TBytes);
|
|
function GetPlatformBytes: TBytes;
|
|
procedure SetPlatformBytes(const Value: TBytes);
|
|
function GetANSI: TBytes;
|
|
procedure SetANSI(const Value: TBytes);
|
|
function GetLast: SystemChar;
|
|
procedure SetLast(const Value: SystemChar);
|
|
function GetFirst: SystemChar;
|
|
procedure SetFirst(const Value: SystemChar);
|
|
function GetUpperChar(index: Integer): SystemChar;
|
|
procedure SetUpperChar(index: Integer; const Value: SystemChar);
|
|
function GetLowerChar(index: Integer): SystemChar;
|
|
procedure SetLowerChar(index: Integer; const Value: SystemChar);
|
|
public
|
|
buff: TArrayChar;
|
|
|
|
{$IFDEF DELPHI}
|
|
class operator Equal(const Lhs, Rhs: TPascalString): Boolean;
|
|
class operator NotEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
class operator GreaterThan(const Lhs, Rhs: TPascalString): Boolean;
|
|
class operator GreaterThanOrEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
class operator LessThan(const Lhs, Rhs: TPascalString): Boolean;
|
|
class operator LessThanOrEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
|
|
class operator Add(const Lhs, Rhs: TPascalString): TPascalString;
|
|
class operator Add(const Lhs: SystemString; const Rhs: TPascalString): TPascalString;
|
|
class operator Add(const Lhs: TPascalString; const Rhs: SystemString): TPascalString;
|
|
class operator Add(const Lhs: SystemChar; const Rhs: TPascalString): TPascalString;
|
|
class operator Add(const Lhs: TPascalString; const Rhs: SystemChar): TPascalString;
|
|
|
|
class operator Implicit(Value: RawByteString): TPascalString;
|
|
class operator Implicit(Value: SystemString): TPascalString;
|
|
class operator Implicit(Value: SystemChar): TPascalString;
|
|
class operator Implicit(Value: TPascalString): SystemString;
|
|
class operator Implicit(Value: TPascalString): Variant;
|
|
|
|
class operator Explicit(Value: TPascalString): RawByteString;
|
|
class operator Explicit(Value: TPascalString): SystemString;
|
|
class operator Explicit(Value: SystemString): TPascalString;
|
|
class operator Explicit(Value: SystemChar): TPascalString;
|
|
class operator Explicit(Value: Variant): TPascalString;
|
|
class operator Explicit(Value: TPascalString): Variant;
|
|
{$ENDIF}
|
|
function Copy(index, Count: NativeInt): TPascalString;
|
|
function Same(const p: PPascalString): Boolean; overload;
|
|
function Same(const t: TPascalString): Boolean; overload;
|
|
function Same(const t1, t2: TPascalString): Boolean; overload;
|
|
function Same(const t1, t2, t3: TPascalString): Boolean; overload;
|
|
function Same(const t1, t2, t3, t4: TPascalString): Boolean; overload;
|
|
function Same(const t1, t2, t3, t4, t5: TPascalString): Boolean; overload;
|
|
function Same(const IgnoreCase: Boolean; const t: TPascalString): Boolean; overload;
|
|
function ComparePos(const Offset: Integer; const p: PPascalString): Boolean; overload;
|
|
function ComparePos(const Offset: Integer; const t: TPascalString): Boolean; overload;
|
|
function GetPos(const s: TPascalString; const Offset: Integer = 1): Integer; overload;
|
|
function GetPos(const s: PPascalString; const Offset: Integer = 1): Integer; overload;
|
|
function Exists(c: SystemChar): Boolean; overload;
|
|
function Exists(c: array of SystemChar): Boolean; overload;
|
|
function Exists(const s: TPascalString): Boolean; overload;
|
|
function GetCharCount(c: SystemChar): Integer;
|
|
|
|
function hash: THash;
|
|
function Hash64: THash64;
|
|
|
|
property Last: SystemChar read GetLast write SetLast;
|
|
property First: SystemChar read GetFirst write SetFirst;
|
|
|
|
procedure DeleteLast;
|
|
procedure DeleteFirst;
|
|
procedure Delete(idx, cnt: Integer);
|
|
procedure Clear;
|
|
procedure Append(t: TPascalString); overload;
|
|
procedure Append(c: SystemChar); overload;
|
|
procedure Append(const Fmt: SystemString; const Args: array of const); overload;
|
|
function GetString(bPos, ePos: NativeInt): TPascalString;
|
|
procedure Insert(AText: SystemString; idx: Integer);
|
|
procedure FastAsText(var output: SystemString);
|
|
procedure FastGetBytes(var output: TBytes);
|
|
property Text: SystemString read GetText write SetText;
|
|
function LowerText: SystemString;
|
|
function UpperText: SystemString;
|
|
function Invert: TPascalString;
|
|
function TrimChar(const Chars: TPascalString): TPascalString;
|
|
function DeleteChar(const Chars: TPascalString): TPascalString; overload;
|
|
function DeleteChar(const Chars: TOrdChars): TPascalString; overload;
|
|
function ReplaceChar(const Chars: TPascalString; const newChar: SystemChar): TPascalString; overload;
|
|
function ReplaceChar(const Chars, newChar: SystemChar): TPascalString; overload;
|
|
function ReplaceChar(const Chars: TOrdChars; const newChar: SystemChar): TPascalString; overload;
|
|
|
|
function BuildPlatformPChar: Pointer;
|
|
class procedure FreePlatformPChar(p: Pointer); static;
|
|
|
|
class function RandomString(L_: Integer): TPascalString; static;
|
|
|
|
{ https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm }
|
|
function SmithWaterman(const p: PPascalString): Double; overload;
|
|
function SmithWaterman(const s: TPascalString): Double; overload;
|
|
|
|
property Len: Integer read GetLen write SetLen;
|
|
property L: Integer read GetLen write SetLen;
|
|
property Chars[index: Integer]: SystemChar read GetChars write SetChars; default;
|
|
property UpperChar[index: Integer]: SystemChar read GetUpperChar write SetUpperChar;
|
|
property LowerChar[index: Integer]: SystemChar read GetLowerChar write SetLowerChar;
|
|
property Bytes: TBytes read GetBytes write SetBytes; // UTF8
|
|
property PlatformBytes: TBytes read GetPlatformBytes write SetPlatformBytes; // system default
|
|
property ANSI: TBytes read GetANSI write SetANSI; // Ansi Bytes
|
|
function BOMBytes: TBytes;
|
|
end;
|
|
|
|
TArrayPascalString = array of TPascalString;
|
|
PArrayPascalString = ^TArrayPascalString;
|
|
|
|
TArrayPascalStringPtr = array of PPascalString;
|
|
PArrayPascalStringPtr = ^TArrayPascalStringPtr;
|
|
|
|
TPStr = TPascalString;
|
|
|
|
function CharIn(c: SystemChar; const SomeChars: array of SystemChar): Boolean; overload;
|
|
function CharIn(c: SystemChar; const SomeChar: SystemChar): Boolean; overload;
|
|
function CharIn(c: SystemChar; const s: TPascalString): Boolean; overload;
|
|
function CharIn(c: SystemChar; const p: PPascalString): Boolean; overload;
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars): Boolean; overload;
|
|
function CharIn(c: SystemChar; const SomeCharset: TOrdChar): Boolean; overload;
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars; const SomeChars: TPascalString): Boolean; overload;
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars; const p: PPascalString): Boolean; overload;
|
|
|
|
function FastHashPSystemString(const s: PSystemString): THash; overload;
|
|
function FastHash64PSystemString(const s: PSystemString): THash64; overload;
|
|
|
|
function FastHashSystemString(const s: SystemString): THash; overload;
|
|
function FastHash64SystemString(const s: SystemString): THash64; overload;
|
|
|
|
function FastHashPPascalString(const s: PPascalString): THash;
|
|
function FastHash64PPascalString(const s: PPascalString): THash64;
|
|
|
|
function PFormat(const Fmt: SystemString; const Args: array of const): SystemString;
|
|
|
|
{$IFDEF FPC}
|
|
|
|
operator := (const s: Variant)r: TPascalString;
|
|
operator := (const s: AnsiString)r: TPascalString;
|
|
operator := (const s: RawByteString)r: TPascalString;
|
|
operator := (const s: UnicodeString)r: TPascalString;
|
|
operator := (const s: WideString)r: TPascalString;
|
|
operator := (const s: ShortString)r: TPascalString;
|
|
operator := (const c: SystemChar)r: TPascalString;
|
|
|
|
operator := (const s: TPascalString)r: AnsiString;
|
|
operator := (const s: TPascalString)r: RawByteString;
|
|
operator := (const s: TPascalString)r: UnicodeString;
|
|
operator := (const s: TPascalString)r: WideString;
|
|
operator := (const s: TPascalString)r: ShortString;
|
|
operator := (const s: TPascalString)r: Variant;
|
|
|
|
operator = (const a: TPascalString; const b: TPascalString): Boolean;
|
|
operator <> (const a: TPascalString; const b: TPascalString): Boolean;
|
|
operator > (const a: TPascalString; const b: TPascalString): Boolean;
|
|
operator >= (const a: TPascalString; const b: TPascalString): Boolean;
|
|
operator < (const a: TPascalString; const b: TPascalString): Boolean;
|
|
operator <= (const a: TPascalString; const b: TPascalString): Boolean;
|
|
|
|
operator + (const a: TPascalString; const b: TPascalString): TPascalString;
|
|
operator + (const a: TPascalString; const b: SystemString): TPascalString;
|
|
operator + (const a: SystemString; const b: TPascalString): TPascalString;
|
|
operator + (const a: TPascalString; const b: SystemChar): TPascalString;
|
|
operator + (const a: SystemChar; const b: TPascalString): TPascalString;
|
|
|
|
{$ENDIF FPC}
|
|
|
|
{ https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm }
|
|
|
|
// short string likeness and out diff
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; var diff1, diff2: TPascalString;
|
|
const NoDiffChar: Boolean; const diffChar: SystemChar): Double; overload;
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; var diff1, diff2: TPascalString): Double; overload;
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString; var diff1, diff2: TPascalString;
|
|
const NoDiffChar: Boolean; const diffChar: SystemChar): Double; overload;
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString; var diff1, diff2: TPascalString): Double; overload;
|
|
|
|
// short string likeness
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; out Same, Diff: Integer): Double; overload;
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString): Double; overload;
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString): Double; overload;
|
|
function SmithWatermanCompare(const seq1: TArrayPascalString; const seq2: TPascalString): Double; overload;
|
|
|
|
// memory likeness
|
|
function SmithWatermanCompare(const seq1: Pointer; siz1: Integer; const seq2: Pointer; siz2: Integer;
|
|
out Same, Diff: Integer): Double; overload;
|
|
function SmithWatermanCompare(const seq1: Pointer; siz1: Integer; const seq2: Pointer; siz2: Integer): Double; overload;
|
|
|
|
// long string likeness
|
|
function SmithWatermanCompareLongString(const t1, t2: TPascalString; const MinDiffCharWithPeerLine: Integer; out Same, Diff: Integer): Double; overload;
|
|
function SmithWatermanCompareLongString(const t1, t2: TPascalString): Double; overload;
|
|
|
|
var
|
|
SystemCharSize: NativeInt = SizeOf(SystemChar);
|
|
{$IFDEF CPU64}
|
|
MaxSmithWatermanMatrix: NativeInt = 10000 * 10;
|
|
{$ELSE}
|
|
MaxSmithWatermanMatrix: NativeInt = 8192;
|
|
{$ENDIF}
|
|
|
|
|
|
const
|
|
{$IFDEF FirstCharInZero}
|
|
FirstCharPos = 0;
|
|
{$ELSE}
|
|
FirstCharPos = 1;
|
|
{$ENDIF}
|
|
|
|
implementation
|
|
|
|
uses SysUtils, Variants;
|
|
|
|
procedure CombineCharsPP(const c1, c2: TArrayChar; var output: TArrayChar);
|
|
var
|
|
LL, rl: Integer;
|
|
begin
|
|
LL := length(c1);
|
|
rl := length(c2);
|
|
SetLength(output, LL + rl);
|
|
if LL > 0 then
|
|
CopyPtr(@c1[0], @output[0], LL * SystemCharSize);
|
|
if rl > 0 then
|
|
CopyPtr(@c2[0], @output[LL], rl * SystemCharSize);
|
|
end;
|
|
|
|
procedure CombineCharsSP(const c1: SystemString; const c2: TArrayChar; var output: TArrayChar);
|
|
var
|
|
LL, rl: Integer;
|
|
begin
|
|
LL := length(c1);
|
|
rl := length(c2);
|
|
SetLength(output, LL + rl);
|
|
if LL > 0 then
|
|
CopyPtr(@c1[FirstCharPos], @output[0], LL * SystemCharSize);
|
|
if rl > 0 then
|
|
CopyPtr(@c2[0], @output[LL], rl * SystemCharSize);
|
|
end;
|
|
|
|
procedure CombineCharsPS(const c1: TArrayChar; const c2: SystemString; var output: TArrayChar);
|
|
var
|
|
LL, rl: Integer;
|
|
begin
|
|
LL := length(c1);
|
|
rl := length(c2);
|
|
SetLength(output, LL + rl);
|
|
if LL > 0 then
|
|
CopyPtr(@c1[0], @output[0], LL * SystemCharSize);
|
|
if rl > 0 then
|
|
CopyPtr(@c2[FirstCharPos], @output[LL], rl * SystemCharSize);
|
|
end;
|
|
|
|
procedure CombineCharsCP(const c1: SystemChar; const c2: TArrayChar; var output: TArrayChar);
|
|
var
|
|
rl: Integer;
|
|
begin
|
|
rl := length(c2);
|
|
SetLength(output, rl + 1);
|
|
output[0] := c1;
|
|
if rl > 0 then
|
|
CopyPtr(@c2[0], @output[1], rl * SystemCharSize);
|
|
end;
|
|
|
|
procedure CombineCharsPC(const c1: TArrayChar; const c2: SystemChar; var output: TArrayChar);
|
|
var
|
|
LL: Integer;
|
|
begin
|
|
LL := length(c1);
|
|
SetLength(output, LL + 1);
|
|
if LL > 0 then
|
|
CopyPtr(@c1[0], @output[0], LL * SystemCharSize);
|
|
output[LL] := c2;
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeChars: array of SystemChar): Boolean;
|
|
var
|
|
AChar: SystemChar;
|
|
begin
|
|
Result := True;
|
|
for AChar in SomeChars do
|
|
if AChar = c then
|
|
Exit;
|
|
Result := False;
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeChar: SystemChar): Boolean;
|
|
begin
|
|
Result := c = SomeChar;
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const s: TPascalString): Boolean;
|
|
begin
|
|
Result := s.Exists(c);
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const p: PPascalString): Boolean;
|
|
begin
|
|
Result := p^.Exists(c);
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeCharset: TOrdChar): Boolean;
|
|
const
|
|
ord0 = Ord('0');
|
|
ord1 = Ord('1');
|
|
ord9 = Ord('9');
|
|
ordLA = Ord('a');
|
|
ordHA = Ord('A');
|
|
ordLF = Ord('f');
|
|
ordHF = Ord('F');
|
|
ordLZ = Ord('z');
|
|
ordHZ = Ord('Z');
|
|
|
|
var
|
|
v: Word;
|
|
begin
|
|
v := Ord(c);
|
|
case SomeCharset of
|
|
c0to9: Result := (v >= ord0) and (v <= ord9);
|
|
c1to9: Result := (v >= ord1) and (v <= ord9);
|
|
c0to32: Result := ((v >= 0) and (v <= 32));
|
|
c0to32no10: Result := ((v >= 0) and (v <= 32) and (v <> 10));
|
|
cLoAtoF: Result := (v >= ordLA) and (v <= ordLF);
|
|
cHiAtoF: Result := (v >= ordHA) and (v <= ordHF);
|
|
cLoAtoZ: Result := (v >= ordLA) and (v <= ordLZ);
|
|
cHiAtoZ: Result := (v >= ordHA) and (v <= ordHZ);
|
|
cHex: Result := ((v >= ordLA) and (v <= ordLF)) or ((v >= ordHA) and (v <= ordHF)) or ((v >= ord0) and (v <= ord9));
|
|
cAtoF: Result := ((v >= ordLA) and (v <= ordLF)) or ((v >= ordHA) and (v <= ordHF));
|
|
cAtoZ: Result := ((v >= ordLA) and (v <= ordLZ)) or ((v >= ordHA) and (v <= ordHZ));
|
|
cVisibled: Result := (v <= $20) and (v <= $7E);
|
|
else Result := False;
|
|
end;
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars): Boolean;
|
|
var
|
|
i: TOrdChar;
|
|
begin
|
|
Result := True;
|
|
for i in SomeCharsets do
|
|
if CharIn(c, i) then
|
|
Exit;
|
|
Result := False;
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars; const SomeChars: TPascalString): Boolean;
|
|
begin
|
|
if CharIn(c, SomeCharsets) then
|
|
Result := True
|
|
else
|
|
Result := CharIn(c, SomeChars);
|
|
end;
|
|
|
|
function CharIn(c: SystemChar; const SomeCharsets: TOrdChars; const p: PPascalString): Boolean;
|
|
begin
|
|
if CharIn(c, SomeCharsets) then
|
|
Result := True
|
|
else
|
|
Result := CharIn(c, p);
|
|
end;
|
|
|
|
function BytesOfPascalString(const s: TPascalString): TBytes;
|
|
begin
|
|
Result := s.Bytes;
|
|
end;
|
|
|
|
function PascalStringOfBytes(const s: TBytes): TPascalString;
|
|
begin
|
|
Result.Bytes := s;
|
|
end;
|
|
|
|
function FastHashPSystemString(const s: PSystemString): THash;
|
|
var
|
|
i: Integer;
|
|
c: SystemChar;
|
|
begin
|
|
Result := 0;
|
|
|
|
{$IFDEF FirstCharInZero}
|
|
for i := 0 to length(s^) - 1 do
|
|
{$ELSE}
|
|
for i := 1 to length(s^) do
|
|
{$ENDIF}
|
|
begin
|
|
c := s^[i];
|
|
if CharIn(c, cHiAtoZ) then
|
|
inc(c, 32);
|
|
Result := ((Result shl 7) or (Result shr 25)) + THash(c);
|
|
end;
|
|
end;
|
|
|
|
function FastHash64PSystemString(const s: PSystemString): THash64;
|
|
var
|
|
i: Integer;
|
|
c: SystemChar;
|
|
begin
|
|
Result := 0;
|
|
|
|
{$IFDEF FirstCharInZero}
|
|
for i := 0 to length(s^) - 1 do
|
|
{$ELSE}
|
|
for i := 1 to length(s^) do
|
|
{$ENDIF}
|
|
begin
|
|
c := s^[i];
|
|
if CharIn(c, cHiAtoZ) then
|
|
inc(c, 32);
|
|
Result := ((Result shl 7) or (Result shr 57)) + THash64(c);
|
|
end;
|
|
end;
|
|
|
|
function FastHashSystemString(const s: SystemString): THash;
|
|
begin
|
|
Result := FastHashPSystemString(@s);
|
|
end;
|
|
|
|
function FastHash64SystemString(const s: SystemString): THash64;
|
|
begin
|
|
Result := FastHash64PSystemString(@s);
|
|
end;
|
|
|
|
function FastHashPPascalString(const s: PPascalString): THash;
|
|
var
|
|
i: Integer;
|
|
c: SystemChar;
|
|
begin
|
|
Result := 0;
|
|
for i := 1 to s^.Len do
|
|
begin
|
|
c := s^[i];
|
|
if CharIn(c, cHiAtoZ) then
|
|
inc(c, 32);
|
|
Result := ((Result shl 7) or (Result shr 25)) + THash(c);
|
|
end;
|
|
end;
|
|
|
|
function FastHash64PPascalString(const s: PPascalString): THash64;
|
|
var
|
|
i: Integer;
|
|
c: SystemChar;
|
|
begin
|
|
Result := 0;
|
|
for i := 1 to s^.Len do
|
|
begin
|
|
c := s^[i];
|
|
if CharIn(c, cHiAtoZ) then
|
|
inc(c, 32);
|
|
Result := ((Result shl 7) or (Result shr 57)) + THash64(c);
|
|
end;
|
|
end;
|
|
|
|
function PFormat(const Fmt: SystemString; const Args: array of const): SystemString;
|
|
begin
|
|
try
|
|
Result := Format(Fmt, Args);
|
|
except
|
|
Result := Fmt;
|
|
end;
|
|
end;
|
|
|
|
function GetSWMVMemory(const xLen, yLen: NativeInt): Pointer; inline;
|
|
{ optimized matrix performance }
|
|
begin
|
|
Result := System.AllocMem((xLen + 1) * (yLen + 1) * SizeOf(NativeInt));
|
|
end;
|
|
|
|
function GetSWMV(const p: Pointer; const w, x, y: NativeInt): NativeInt; inline;
|
|
{ optimized matrix performance }
|
|
begin
|
|
Result := PNativeInt(nativeUInt(p) + ((x + y * (w + 1)) * SizeOf(NativeInt)))^;
|
|
end;
|
|
|
|
procedure SetSWMV(const p: Pointer; const w, x, y: NativeInt; const v: NativeInt); inline;
|
|
{ optimized matrix performance }
|
|
begin
|
|
PNativeInt(nativeUInt(p) + ((x + y * (w + 1)) * SizeOf(NativeInt)))^ := v;
|
|
end;
|
|
|
|
function GetMax(const i1, i2: NativeInt): NativeInt; inline;
|
|
begin
|
|
if i1 > i2 then
|
|
Result := i1
|
|
else
|
|
Result := i2;
|
|
end;
|
|
|
|
const
|
|
SmithWaterman_MatchOk = 1;
|
|
mismatch_penalty = -1;
|
|
gap_penalty = -1;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; var diff1, diff2: TPascalString;
|
|
const NoDiffChar: Boolean; const diffChar: SystemChar): Double;
|
|
|
|
function InlineMatch(alphaC, betaC: SystemChar; const diffC: SystemChar): Integer; inline;
|
|
begin
|
|
if CharIn(alphaC, cLoAtoZ) then
|
|
dec(alphaC, 32);
|
|
if CharIn(betaC, cLoAtoZ) then
|
|
dec(betaC, 32);
|
|
|
|
if alphaC = betaC then
|
|
Result := SmithWaterman_MatchOk
|
|
else if (alphaC = diffC) or (betaC = diffC) then
|
|
Result := gap_penalty
|
|
else
|
|
Result := mismatch_penalty;
|
|
end;
|
|
|
|
var
|
|
swMatrixPtr: Pointer;
|
|
i, j, L1, l2: NativeInt;
|
|
matched, deleted, inserted: NativeInt;
|
|
score_current, score_diagonal, score_left, score_right: NativeInt;
|
|
identity: NativeInt;
|
|
align1, align2: TPascalString;
|
|
begin
|
|
L1 := seq1^.Len;
|
|
l2 := seq2^.Len;
|
|
|
|
if (L1 = 0) or (l2 = 0) or (L1 > MaxSmithWatermanMatrix) or (l2 > MaxSmithWatermanMatrix) then
|
|
begin
|
|
Result := -1;
|
|
Exit;
|
|
end;
|
|
|
|
{ fast build matrix }
|
|
swMatrixPtr := GetSWMVMemory(L1, l2);
|
|
if swMatrixPtr = nil then
|
|
begin
|
|
diff1 := '';
|
|
diff2 := '';
|
|
Result := -1;
|
|
Exit;
|
|
end;
|
|
|
|
i := 0;
|
|
while i <= L1 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, i, 0, gap_penalty * i);
|
|
inc(i);
|
|
end;
|
|
|
|
j := 0;
|
|
while j <= l2 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, 0, j, gap_penalty * j);
|
|
inc(j);
|
|
end;
|
|
|
|
{ compute matrix }
|
|
i := 1;
|
|
while i <= L1 do
|
|
begin
|
|
j := 1;
|
|
while j <= l2 do
|
|
begin
|
|
matched := GetSWMV(swMatrixPtr, L1, i - 1, j - 1) + InlineMatch(seq1^[i], seq2^[j], diffChar);
|
|
deleted := GetSWMV(swMatrixPtr, L1, i - 1, j) + gap_penalty;
|
|
inserted := GetSWMV(swMatrixPtr, L1, i, j - 1) + gap_penalty;
|
|
SetSWMV(swMatrixPtr, L1, i, j, GetMax(matched, GetMax(deleted, inserted)));
|
|
inc(j);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
|
|
{ compute align }
|
|
i := L1;
|
|
j := l2;
|
|
align1 := '';
|
|
align2 := '';
|
|
identity := 0;
|
|
while (i > 0) and (j > 0) do
|
|
begin
|
|
score_current := GetSWMV(swMatrixPtr, L1, i, j);
|
|
score_diagonal := GetSWMV(swMatrixPtr, L1, i - 1, j - 1);
|
|
score_left := GetSWMV(swMatrixPtr, L1, i - 1, j);
|
|
score_right := GetSWMV(swMatrixPtr, L1, i, j - 1);
|
|
|
|
matched := InlineMatch(seq1^[i], seq2^[j], diffChar);
|
|
|
|
if score_current = score_diagonal + matched then
|
|
begin
|
|
if matched = SmithWaterman_MatchOk then
|
|
begin
|
|
inc(identity);
|
|
align1.Append(seq1^[i]);
|
|
align2.Append(seq2^[j]);
|
|
end
|
|
else if NoDiffChar then
|
|
begin
|
|
align1.Append(diffChar);
|
|
align2.Append(diffChar);
|
|
end
|
|
else
|
|
begin
|
|
align1.Append(seq1^[i]);
|
|
align2.Append(seq2^[j]);
|
|
end;
|
|
dec(i);
|
|
dec(j);
|
|
end
|
|
else if score_current = score_left + gap_penalty then
|
|
begin
|
|
if NoDiffChar then
|
|
align1.Append(diffChar)
|
|
else
|
|
align1.Append(seq1^[i]);
|
|
align2.Append(diffChar);
|
|
dec(i);
|
|
end
|
|
else if score_current = score_right + gap_penalty then
|
|
begin
|
|
if NoDiffChar then
|
|
align2.Append(diffChar)
|
|
else
|
|
align2.Append(seq2^[j]);
|
|
align1.Append(diffChar);
|
|
dec(j);
|
|
end
|
|
else
|
|
raise Exception.Create('matrix error'); // matrix debug time
|
|
end;
|
|
|
|
System.FreeMemory(swMatrixPtr);
|
|
|
|
while i > 0 do
|
|
begin
|
|
if NoDiffChar then
|
|
align1.Append(diffChar)
|
|
else
|
|
align1.Append(seq1^[i]);
|
|
align2.Append(diffChar);
|
|
dec(i);
|
|
end;
|
|
|
|
while j > 0 do
|
|
begin
|
|
if NoDiffChar then
|
|
align2.Append(diffChar)
|
|
else
|
|
align2.Append(seq2^[j]);
|
|
align1.Append(diffChar);
|
|
dec(j);
|
|
end;
|
|
|
|
if identity > 0 then
|
|
Result := identity / align1.Len
|
|
else
|
|
Result := -1;
|
|
|
|
diff1 := align1.Invert;
|
|
diff2 := align2.Invert;
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; var diff1, diff2: TPascalString): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(seq1, seq2, diff1, diff2, False, '-');
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString; var diff1, diff2: TPascalString;
|
|
const NoDiffChar: Boolean; const diffChar: SystemChar): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(@seq1, @seq2, diff1, diff2, NoDiffChar, diffChar);
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString; var diff1, diff2: TPascalString): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(seq1, seq2, diff1, diff2, False, '-');
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString; out Same, Diff: Integer): Double;
|
|
|
|
function InlineMatch(alphaC, betaC: SystemChar): NativeInt; inline;
|
|
begin
|
|
if CharIn(alphaC, cLoAtoZ) then
|
|
dec(alphaC, 32);
|
|
if CharIn(betaC, cLoAtoZ) then
|
|
dec(betaC, 32);
|
|
|
|
if alphaC = betaC then
|
|
Result := SmithWaterman_MatchOk
|
|
else
|
|
Result := mismatch_penalty;
|
|
end;
|
|
|
|
var
|
|
swMatrixPtr: Pointer;
|
|
i, j, L1, l2: NativeInt;
|
|
matched, deleted, inserted: NativeInt;
|
|
score_current, score_diagonal, score_left, score_right: NativeInt;
|
|
identity, L_: NativeInt;
|
|
begin
|
|
L1 := seq1^.Len;
|
|
l2 := seq2^.Len;
|
|
|
|
if (L1 = 0) or (l2 = 0) or (L1 > MaxSmithWatermanMatrix) or (l2 > MaxSmithWatermanMatrix) then
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := L1 + l2;
|
|
Exit;
|
|
end;
|
|
|
|
{ fast build matrix }
|
|
swMatrixPtr := GetSWMVMemory(L1, l2);
|
|
if swMatrixPtr = nil then
|
|
begin
|
|
Result := -1;
|
|
Exit;
|
|
end;
|
|
|
|
i := 0;
|
|
while i <= L1 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, i, 0, gap_penalty * i);
|
|
inc(i);
|
|
end;
|
|
|
|
j := 0;
|
|
while j <= l2 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, 0, j, gap_penalty * j);
|
|
inc(j);
|
|
end;
|
|
|
|
{ compute matrix }
|
|
i := 1;
|
|
while i <= L1 do
|
|
begin
|
|
j := 1;
|
|
while j <= l2 do
|
|
begin
|
|
matched := GetSWMV(swMatrixPtr, L1, i - 1, j - 1) + InlineMatch(seq1^[i], seq2^[j]);
|
|
deleted := GetSWMV(swMatrixPtr, L1, i - 1, j) + gap_penalty;
|
|
inserted := GetSWMV(swMatrixPtr, L1, i, j - 1) + gap_penalty;
|
|
SetSWMV(swMatrixPtr, L1, i, j, GetMax(matched, GetMax(deleted, inserted)));
|
|
inc(j);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
|
|
{ compute align }
|
|
i := L1;
|
|
j := l2;
|
|
identity := 0;
|
|
L_ := 0;
|
|
while (i > 0) and (j > 0) do
|
|
begin
|
|
score_current := GetSWMV(swMatrixPtr, L1, i, j);
|
|
score_diagonal := GetSWMV(swMatrixPtr, L1, i - 1, j - 1);
|
|
score_left := GetSWMV(swMatrixPtr, L1, i - 1, j);
|
|
score_right := GetSWMV(swMatrixPtr, L1, i, j - 1);
|
|
matched := InlineMatch(seq1^[i], seq2^[j]);
|
|
|
|
if score_current = score_diagonal + matched then
|
|
begin
|
|
if matched = SmithWaterman_MatchOk then
|
|
inc(identity);
|
|
|
|
inc(L_);
|
|
dec(i);
|
|
dec(j);
|
|
end
|
|
else if score_current = score_left + gap_penalty then
|
|
begin
|
|
inc(L_);
|
|
dec(i);
|
|
end
|
|
else if score_current = score_right + gap_penalty then
|
|
begin
|
|
inc(L_);
|
|
dec(j);
|
|
end
|
|
else
|
|
raise Exception.Create('matrix error'); // matrix debug time
|
|
end;
|
|
|
|
System.FreeMemory(swMatrixPtr);
|
|
|
|
if identity > 0 then
|
|
begin
|
|
Result := identity / (L_ + i + j);
|
|
Same := identity;
|
|
Diff := (L_ + i + j) - identity;
|
|
end
|
|
else
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := L_ + i + j;
|
|
end;
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: PPascalString): Double;
|
|
var
|
|
Same, Diff: Integer;
|
|
begin
|
|
Result := SmithWatermanCompare(seq1, seq2, Same, Diff);
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1, seq2: TPascalString): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(@seq1, @seq2);
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1: TArrayPascalString; const seq2: TPascalString): Double;
|
|
var
|
|
i: Integer;
|
|
r: Double;
|
|
begin
|
|
Result := -1;
|
|
for i := 0 to length(seq1) - 1 do
|
|
begin
|
|
r := SmithWatermanCompare(seq1[i], seq2);
|
|
if r > Result then
|
|
Result := r;
|
|
end;
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1: Pointer; siz1: Integer; const seq2: Pointer; siz2: Integer;
|
|
out Same, Diff: Integer): Double;
|
|
|
|
function InlineMatch(const alphaB, betaB: Byte): NativeInt; inline;
|
|
begin
|
|
if alphaB = betaB then
|
|
Result := SmithWaterman_MatchOk
|
|
else
|
|
Result := mismatch_penalty;
|
|
end;
|
|
|
|
var
|
|
swMatrixPtr: Pointer;
|
|
i, j, L1, l2: NativeInt;
|
|
matched, deleted, inserted: NativeInt;
|
|
score_current, score_diagonal, score_left, score_right: NativeInt;
|
|
identity, L_: NativeInt;
|
|
begin
|
|
L1 := siz1;
|
|
l2 := siz2;
|
|
|
|
if (L1 = 0) or (l2 = 0) or (L1 > MaxSmithWatermanMatrix) or (l2 > MaxSmithWatermanMatrix) then
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := L1 + l2;
|
|
Exit;
|
|
end;
|
|
|
|
{ fast build matrix }
|
|
swMatrixPtr := GetSWMVMemory(L1, l2);
|
|
if swMatrixPtr = nil then
|
|
begin
|
|
Result := -1;
|
|
Exit;
|
|
end;
|
|
|
|
i := 0;
|
|
while i <= L1 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, i, 0, gap_penalty * i);
|
|
inc(i);
|
|
end;
|
|
|
|
j := 0;
|
|
while j <= l2 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, 0, j, gap_penalty * j);
|
|
inc(j);
|
|
end;
|
|
|
|
{ compute matrix }
|
|
i := 1;
|
|
while i <= L1 do
|
|
begin
|
|
j := 1;
|
|
while j <= l2 do
|
|
begin
|
|
matched := GetSWMV(swMatrixPtr, L1, i - 1, j - 1) + InlineMatch(PByte(nativeUInt(seq1) + (i - 1))^, PByte(nativeUInt(seq2) + (j - 1))^);
|
|
deleted := GetSWMV(swMatrixPtr, L1, i - 1, j) + gap_penalty;
|
|
inserted := GetSWMV(swMatrixPtr, L1, i, j - 1) + gap_penalty;
|
|
SetSWMV(swMatrixPtr, L1, i, j, GetMax(matched, GetMax(deleted, inserted)));
|
|
inc(j);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
|
|
{ compute align }
|
|
i := L1;
|
|
j := l2;
|
|
identity := 0;
|
|
L_ := 0;
|
|
while (i > 0) and (j > 0) do
|
|
begin
|
|
score_current := GetSWMV(swMatrixPtr, L1, i, j);
|
|
score_diagonal := GetSWMV(swMatrixPtr, L1, i - 1, j - 1);
|
|
score_left := GetSWMV(swMatrixPtr, L1, i - 1, j);
|
|
score_right := GetSWMV(swMatrixPtr, L1, i, j - 1);
|
|
matched := InlineMatch(PByte(nativeUInt(seq1) + (i - 1))^, PByte(nativeUInt(seq2) + (j - 1))^);
|
|
|
|
if score_current = score_diagonal + matched then
|
|
begin
|
|
if matched = SmithWaterman_MatchOk then
|
|
inc(identity);
|
|
|
|
inc(L_);
|
|
dec(i);
|
|
dec(j);
|
|
end
|
|
else if score_current = score_left + gap_penalty then
|
|
begin
|
|
inc(L_);
|
|
dec(i);
|
|
end
|
|
else if score_current = score_right + gap_penalty then
|
|
begin
|
|
inc(L_);
|
|
dec(j);
|
|
end
|
|
else
|
|
raise Exception.Create('matrix error'); // matrix debug time
|
|
end;
|
|
|
|
System.FreeMemory(swMatrixPtr);
|
|
|
|
if identity > 0 then
|
|
begin
|
|
Result := identity / (L_ + i + j);
|
|
Same := identity;
|
|
Diff := (L_ + i + j) - identity;
|
|
end
|
|
else
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := L_ + i + j;
|
|
end;
|
|
end;
|
|
|
|
function SmithWatermanCompare(const seq1: Pointer; siz1: Integer; const seq2: Pointer; siz2: Integer): Double;
|
|
var
|
|
Same, Diff: Integer;
|
|
begin
|
|
Result := SmithWatermanCompare(seq1, siz1, seq2, siz2, Same, Diff);
|
|
end;
|
|
|
|
function SmithWatermanCompareLongString(const t1, t2: TPascalString; const MinDiffCharWithPeerLine: Integer; out Same, Diff: Integer): Double;
|
|
type
|
|
PSRec = ^TSRec;
|
|
|
|
TSRec = record
|
|
s: TPascalString;
|
|
end;
|
|
|
|
procedure _FillText(psPtr: PPascalString; outLst: TCoreClassList);
|
|
var
|
|
L_, i: Integer;
|
|
n: TPascalString;
|
|
p: PSRec;
|
|
begin
|
|
L_ := psPtr^.Len;
|
|
i := 1;
|
|
n := '';
|
|
while i <= L_ do
|
|
begin
|
|
if CharIn(psPtr^[i], [#13, #10]) then
|
|
begin
|
|
n := n.DeleteChar(#32#9);
|
|
if n.Len > 0 then
|
|
begin
|
|
new(p);
|
|
p^.s := n;
|
|
outLst.Add(p);
|
|
n := '';
|
|
end;
|
|
repeat
|
|
inc(i);
|
|
until (i > L_) or (not CharIn(psPtr^[i], [#13, #10, #32, #9]));
|
|
end
|
|
else
|
|
begin
|
|
n.Append(psPtr^[i]);
|
|
inc(i);
|
|
end;
|
|
end;
|
|
|
|
n := n.DeleteChar(#32#9);
|
|
if n.Len > 0 then
|
|
begin
|
|
new(p);
|
|
p^.s := n;
|
|
outLst.Add(p);
|
|
end;
|
|
end;
|
|
|
|
function InlineMatch(const alpha, beta: PSRec; const MinDiffCharWithPeerLine: Integer; var cSame, cDiff: Integer): NativeInt; inline;
|
|
begin
|
|
if SmithWatermanCompare(@alpha^.s, @beta^.s, cSame, cDiff) > 0 then
|
|
begin
|
|
if cDiff < MinDiffCharWithPeerLine then
|
|
Result := SmithWaterman_MatchOk
|
|
else
|
|
Result := mismatch_penalty;
|
|
end
|
|
else
|
|
Result := mismatch_penalty;
|
|
end;
|
|
|
|
var
|
|
lst1, lst2: TCoreClassList;
|
|
|
|
procedure _Init;
|
|
begin
|
|
lst1 := TCoreClassList.Create;
|
|
lst2 := TCoreClassList.Create;
|
|
_FillText(@t1, lst1);
|
|
_FillText(@t2, lst2);
|
|
end;
|
|
|
|
procedure _Free;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to lst1.Count - 1 do
|
|
Dispose(PSRec(lst1[i]));
|
|
for i := 0 to lst2.Count - 1 do
|
|
Dispose(PSRec(lst2[i]));
|
|
DisposeObject([lst1, lst2]);
|
|
end;
|
|
|
|
var
|
|
swMatrixPtr: Pointer;
|
|
i, j, L1, l2: NativeInt;
|
|
matched, deleted, inserted: NativeInt;
|
|
score_current, score_diagonal, score_left, score_right: NativeInt;
|
|
cSame, cDiff, TotalSame, TotalDiff: Integer;
|
|
begin
|
|
_Init;
|
|
L1 := lst1.Count;
|
|
l2 := lst2.Count;
|
|
|
|
if (L1 = 0) or (l2 = 0) or (L1 > MaxSmithWatermanMatrix) or (l2 > MaxSmithWatermanMatrix) then
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := L1 + l2;
|
|
_Free;
|
|
Exit;
|
|
end;
|
|
|
|
{ fast build matrix }
|
|
swMatrixPtr := GetSWMVMemory(L1, l2);
|
|
if swMatrixPtr = nil then
|
|
begin
|
|
Result := -1;
|
|
_Free;
|
|
Exit;
|
|
end;
|
|
|
|
i := 0;
|
|
while i <= L1 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, i, 0, gap_penalty * i);
|
|
inc(i);
|
|
end;
|
|
|
|
j := 0;
|
|
while j <= l2 do
|
|
begin
|
|
SetSWMV(swMatrixPtr, L1, 0, j, gap_penalty * j);
|
|
inc(j);
|
|
end;
|
|
|
|
{ compute matrix }
|
|
i := 1;
|
|
while i <= L1 do
|
|
begin
|
|
j := 1;
|
|
while j <= l2 do
|
|
begin
|
|
matched := GetSWMV(swMatrixPtr, L1, i - 1, j - 1) + InlineMatch(PSRec(lst1[i - 1]), PSRec(lst2[j - 1]), MinDiffCharWithPeerLine, cSame, cDiff);
|
|
deleted := GetSWMV(swMatrixPtr, L1, i - 1, j) + gap_penalty;
|
|
inserted := GetSWMV(swMatrixPtr, L1, i, j - 1) + gap_penalty;
|
|
SetSWMV(swMatrixPtr, L1, i, j, GetMax(matched, GetMax(deleted, inserted)));
|
|
inc(j);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
|
|
{ compute align }
|
|
i := L1;
|
|
j := l2;
|
|
TotalSame := 0;
|
|
TotalDiff := 0;
|
|
while (i > 0) and (j > 0) do
|
|
begin
|
|
score_current := GetSWMV(swMatrixPtr, L1, i, j);
|
|
score_diagonal := GetSWMV(swMatrixPtr, L1, i - 1, j - 1);
|
|
score_left := GetSWMV(swMatrixPtr, L1, i - 1, j);
|
|
score_right := GetSWMV(swMatrixPtr, L1, i, j - 1);
|
|
matched := InlineMatch(PSRec(lst1[i - 1]), PSRec(lst2[j - 1]), MinDiffCharWithPeerLine, cSame, cDiff);
|
|
|
|
inc(TotalSame, cSame);
|
|
inc(TotalDiff, cDiff);
|
|
|
|
if score_current = score_diagonal + matched then
|
|
begin
|
|
dec(i);
|
|
dec(j);
|
|
end
|
|
else if score_current = score_left + gap_penalty then
|
|
begin
|
|
dec(i);
|
|
end
|
|
else if score_current = score_right + gap_penalty then
|
|
begin
|
|
dec(j);
|
|
end
|
|
else
|
|
raise Exception.Create('matrix error'); // matrix debug time
|
|
end;
|
|
|
|
System.FreeMemory(swMatrixPtr);
|
|
_Free;
|
|
|
|
if TotalSame > 0 then
|
|
begin
|
|
Result := TotalSame / (TotalSame + TotalDiff);
|
|
Same := TotalSame;
|
|
Diff := TotalDiff;
|
|
end
|
|
else
|
|
begin
|
|
Result := -1;
|
|
Same := 0;
|
|
Diff := t2.Len + t1.Len;
|
|
end;
|
|
end;
|
|
|
|
function SmithWatermanCompareLongString(const t1, t2: TPascalString): Double;
|
|
var
|
|
Same, Diff: Integer;
|
|
begin
|
|
Result := SmithWatermanCompareLongString(t1, t2, 5, Same, Diff);
|
|
end;
|
|
|
|
{$IFDEF FPC}
|
|
|
|
|
|
operator := (const s: Variant)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const s: AnsiString)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const s: RawByteString)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const s: UnicodeString)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const s: WideString)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const s: ShortString)r: TPascalString;
|
|
begin
|
|
r.Text := s;
|
|
end;
|
|
|
|
operator := (const c: SystemChar)r: TPascalString;
|
|
begin
|
|
r.Text := c;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: AnsiString;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: RawByteString;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: UnicodeString;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: WideString;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: ShortString;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator := (const s: TPascalString)r: Variant;
|
|
begin
|
|
r := s.Text;
|
|
end;
|
|
|
|
operator = (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text = b.Text;
|
|
end;
|
|
|
|
operator <> (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text <> b.Text;
|
|
end;
|
|
|
|
operator > (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text > b.Text;
|
|
end;
|
|
|
|
operator >= (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text >= b.Text;
|
|
end;
|
|
|
|
operator < (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text < b.Text;
|
|
end;
|
|
|
|
operator <= (const a: TPascalString; const b: TPascalString): Boolean;
|
|
begin
|
|
Result := a.Text <= b.Text;
|
|
end;
|
|
|
|
operator + (const a: TPascalString; const b: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsPP(a.buff, b.buff, Result.buff);
|
|
end;
|
|
|
|
operator + (const a: TPascalString; const b: SystemString): TPascalString;
|
|
begin
|
|
CombineCharsPS(a.buff, b, Result.buff);
|
|
end;
|
|
|
|
operator + (const a: SystemString; const b: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsSP(a, b.buff, Result.buff);
|
|
end;
|
|
|
|
operator + (const a: TPascalString; const b: SystemChar): TPascalString;
|
|
begin
|
|
CombineCharsPC(a.buff, b, Result.buff);
|
|
end;
|
|
|
|
operator + (const a: SystemChar; const b: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsCP(a, b.buff, Result.buff);
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
function TPascalString.GetText: SystemString;
|
|
begin
|
|
SetLength(Result, length(buff));
|
|
if length(buff) > 0 then
|
|
CopyPtr(@buff[0], @Result[FirstCharPos], length(buff) * SystemCharSize);
|
|
end;
|
|
|
|
procedure TPascalString.SetText(const Value: SystemString);
|
|
begin
|
|
SetLength(buff, length(Value));
|
|
|
|
if length(buff) > 0 then
|
|
CopyPtr(@Value[FirstCharPos], @buff[0], length(buff) * SystemCharSize);
|
|
end;
|
|
|
|
function TPascalString.GetLen: Integer;
|
|
begin
|
|
Result := length(buff);
|
|
end;
|
|
|
|
procedure TPascalString.SetLen(const Value: Integer);
|
|
begin
|
|
SetLength(buff, Value);
|
|
end;
|
|
|
|
function TPascalString.GetChars(index: Integer): SystemChar;
|
|
begin
|
|
if (index > length(buff)) or (index <= 0) then
|
|
Result := #0
|
|
else
|
|
Result := buff[index - 1];
|
|
end;
|
|
|
|
procedure TPascalString.SetChars(index: Integer; const Value: SystemChar);
|
|
begin
|
|
buff[index - 1] := Value;
|
|
end;
|
|
|
|
function TPascalString.GetBytes: TBytes;
|
|
begin
|
|
SetLength(Result, 0);
|
|
if length(buff) = 0 then
|
|
Exit;
|
|
{$IFDEF FPC}
|
|
Result := SysUtils.TEncoding.UTF8.GetBytes(Text);
|
|
{$ELSE}
|
|
Result := SysUtils.TEncoding.UTF8.GetBytes(buff);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TPascalString.SetBytes(const Value: TBytes);
|
|
begin
|
|
SetLength(buff, 0);
|
|
if length(Value) = 0 then
|
|
Exit;
|
|
try
|
|
Text := SysUtils.TEncoding.UTF8.GetString(Value);
|
|
except
|
|
SetPlatformBytes(Value);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.GetPlatformBytes: TBytes;
|
|
begin
|
|
SetLength(Result, 0);
|
|
if length(buff) = 0 then
|
|
Exit;
|
|
{$IFDEF FPC}
|
|
Result := SysUtils.TEncoding.Default.GetBytes(Text);
|
|
{$ELSE}
|
|
Result := SysUtils.TEncoding.Default.GetBytes(buff);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TPascalString.SetPlatformBytes(const Value: TBytes);
|
|
begin
|
|
SetLength(buff, 0);
|
|
if length(Value) = 0 then
|
|
Exit;
|
|
try
|
|
Text := SysUtils.TEncoding.Default.GetString(Value);
|
|
except
|
|
SetLength(buff, 0);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.GetANSI: TBytes;
|
|
begin
|
|
SetLength(Result, 0);
|
|
if length(buff) = 0 then
|
|
Exit;
|
|
{$IFDEF FPC}
|
|
Result := SysUtils.TEncoding.ANSI.GetBytes(Text);
|
|
{$ELSE}
|
|
Result := SysUtils.TEncoding.ANSI.GetBytes(buff);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TPascalString.SetANSI(const Value: TBytes);
|
|
begin
|
|
SetLength(buff, 0);
|
|
if length(Value) = 0 then
|
|
Exit;
|
|
try
|
|
Text := SysUtils.TEncoding.ANSI.GetString(Value);
|
|
except
|
|
SetLength(buff, 0);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.GetLast: SystemChar;
|
|
begin
|
|
if length(buff) > 0 then
|
|
Result := buff[length(buff) - 1]
|
|
else
|
|
Result := #0;
|
|
end;
|
|
|
|
procedure TPascalString.SetLast(const Value: SystemChar);
|
|
begin
|
|
buff[length(buff) - 1] := Value;
|
|
end;
|
|
|
|
function TPascalString.GetFirst: SystemChar;
|
|
begin
|
|
if length(buff) > 0 then
|
|
Result := buff[0]
|
|
else
|
|
Result := #0;
|
|
end;
|
|
|
|
procedure TPascalString.SetFirst(const Value: SystemChar);
|
|
begin
|
|
buff[0] := Value;
|
|
end;
|
|
|
|
function TPascalString.GetUpperChar(index: Integer): SystemChar;
|
|
begin
|
|
Result := GetChars(index);
|
|
if CharIn(Result, cLoAtoZ) then
|
|
Result := SystemChar(Word(Result) xor $0020);
|
|
end;
|
|
|
|
procedure TPascalString.SetUpperChar(index: Integer; const Value: SystemChar);
|
|
begin
|
|
if CharIn(Value, cLoAtoZ) then
|
|
SetChars(index, SystemChar(Word(Value) xor $0020))
|
|
else
|
|
SetChars(index, Value);
|
|
end;
|
|
|
|
function TPascalString.GetLowerChar(index: Integer): SystemChar;
|
|
begin
|
|
Result := GetChars(index);
|
|
if CharIn(Result, cHiAtoZ) then
|
|
Result := SystemChar(Word(Result) or $0020);
|
|
end;
|
|
|
|
procedure TPascalString.SetLowerChar(index: Integer; const Value: SystemChar);
|
|
begin
|
|
if CharIn(Value, cHiAtoZ) then
|
|
SetChars(index, SystemChar(Word(Value) or $0020))
|
|
else
|
|
SetChars(index, Value);
|
|
end;
|
|
|
|
{$IFDEF DELPHI}
|
|
|
|
|
|
class operator TPascalString.Equal(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := (Lhs.Len = Rhs.Len) and (Lhs.Text = Rhs.Text);
|
|
end;
|
|
|
|
class operator TPascalString.NotEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := not(Lhs = Rhs);
|
|
end;
|
|
|
|
class operator TPascalString.GreaterThan(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := Lhs.Text > Rhs.Text;
|
|
end;
|
|
|
|
class operator TPascalString.GreaterThanOrEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := Lhs.Text >= Rhs.Text;
|
|
end;
|
|
|
|
class operator TPascalString.LessThan(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := Lhs.Text < Rhs.Text;
|
|
end;
|
|
|
|
class operator TPascalString.LessThanOrEqual(const Lhs, Rhs: TPascalString): Boolean;
|
|
begin
|
|
Result := Lhs.Text <= Rhs.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Add(const Lhs, Rhs: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsPP(Lhs.buff, Rhs.buff, Result.buff);
|
|
end;
|
|
|
|
class operator TPascalString.Add(const Lhs: SystemString; const Rhs: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsSP(Lhs, Rhs.buff, Result.buff);
|
|
end;
|
|
|
|
class operator TPascalString.Add(const Lhs: TPascalString; const Rhs: SystemString): TPascalString;
|
|
begin
|
|
CombineCharsPS(Lhs.buff, Rhs, Result.buff);
|
|
end;
|
|
|
|
class operator TPascalString.Add(const Lhs: SystemChar; const Rhs: TPascalString): TPascalString;
|
|
begin
|
|
CombineCharsCP(Lhs, Rhs.buff, Result.buff);
|
|
end;
|
|
|
|
class operator TPascalString.Add(const Lhs: TPascalString; const Rhs: SystemChar): TPascalString;
|
|
begin
|
|
CombineCharsPC(Lhs.buff, Rhs, Result.buff);
|
|
end;
|
|
|
|
class operator TPascalString.Implicit(Value: RawByteString): TPascalString;
|
|
begin
|
|
Result.Text := Value;
|
|
end;
|
|
|
|
class operator TPascalString.Implicit(Value: SystemString): TPascalString;
|
|
begin
|
|
Result.Text := Value;
|
|
end;
|
|
|
|
class operator TPascalString.Implicit(Value: SystemChar): TPascalString;
|
|
begin
|
|
Result.Len := 1;
|
|
Result.buff[0] := Value;
|
|
end;
|
|
|
|
class operator TPascalString.Implicit(Value: TPascalString): SystemString;
|
|
begin
|
|
Result := Value.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Implicit(Value: TPascalString): Variant;
|
|
begin
|
|
Result := Value.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: TPascalString): RawByteString;
|
|
begin
|
|
Result := Value.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: TPascalString): SystemString;
|
|
begin
|
|
Result := Value.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: TPascalString): Variant;
|
|
begin
|
|
Result := Value.Text;
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: SystemString): TPascalString;
|
|
begin
|
|
Result.Text := Value;
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: Variant): TPascalString;
|
|
begin
|
|
Result.Text := VarToStr(Value);
|
|
end;
|
|
|
|
class operator TPascalString.Explicit(Value: SystemChar): TPascalString;
|
|
begin
|
|
Result.Len := 1;
|
|
Result.buff[0] := Value;
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
function TPascalString.Copy(index, Count: NativeInt): TPascalString;
|
|
var
|
|
L_: NativeInt;
|
|
begin
|
|
L_ := length(buff);
|
|
|
|
if (index - 1) + Count > L_ then
|
|
Count := L_ - (index - 1);
|
|
|
|
SetLength(Result.buff, Count);
|
|
if Count > 0 then
|
|
CopyPtr(@buff[index - 1], @Result.buff[0], SystemCharSize * Count);
|
|
end;
|
|
|
|
function TPascalString.Same(const p: PPascalString): Boolean;
|
|
var
|
|
i: Integer;
|
|
s, d: SystemChar;
|
|
begin
|
|
Result := (p^.Len = Len);
|
|
if not Result then
|
|
Exit;
|
|
for i := 0 to Len - 1 do
|
|
begin
|
|
s := buff[i];
|
|
if CharIn(s, cHiAtoZ) then
|
|
inc(s, 32);
|
|
d := p^.buff[i];
|
|
if CharIn(d, cHiAtoZ) then
|
|
inc(d, 32);
|
|
if s <> d then
|
|
Exit(False);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.Same(const t: TPascalString): Boolean;
|
|
var
|
|
i: Integer;
|
|
s, d: SystemChar;
|
|
begin
|
|
Result := (t.Len = Len);
|
|
if not Result then
|
|
Exit;
|
|
for i := 0 to Len - 1 do
|
|
begin
|
|
s := buff[i];
|
|
if CharIn(s, cHiAtoZ) then
|
|
inc(s, 32);
|
|
d := t.buff[i];
|
|
if CharIn(d, cHiAtoZ) then
|
|
inc(d, 32);
|
|
if s <> d then
|
|
Exit(False);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.Same(const t1, t2: TPascalString): Boolean;
|
|
begin
|
|
Result := Same(@t1) or Same(@t2);
|
|
end;
|
|
|
|
function TPascalString.Same(const t1, t2, t3: TPascalString): Boolean;
|
|
begin
|
|
Result := Same(@t1) or Same(@t2) or Same(@t3);
|
|
end;
|
|
|
|
function TPascalString.Same(const t1, t2, t3, t4: TPascalString): Boolean;
|
|
begin
|
|
Result := Same(@t1) or Same(@t2) or Same(@t3) or Same(@t4);
|
|
end;
|
|
|
|
function TPascalString.Same(const t1, t2, t3, t4, t5: TPascalString): Boolean;
|
|
begin
|
|
Result := Same(@t1) or Same(@t2) or Same(@t3) or Same(@t4) or Same(@t5);
|
|
end;
|
|
|
|
function TPascalString.Same(const IgnoreCase: Boolean; const t: TPascalString): Boolean;
|
|
var
|
|
i: Integer;
|
|
s, d: SystemChar;
|
|
begin
|
|
Result := (t.Len = Len);
|
|
if not Result then
|
|
Exit;
|
|
for i := 0 to Len - 1 do
|
|
begin
|
|
s := buff[i];
|
|
if IgnoreCase then
|
|
if CharIn(s, cHiAtoZ) then
|
|
inc(s, 32);
|
|
|
|
d := t.buff[i];
|
|
if IgnoreCase then
|
|
if CharIn(d, cHiAtoZ) then
|
|
inc(d, 32);
|
|
|
|
if s <> d then
|
|
Exit(False);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.ComparePos(const Offset: Integer; const p: PPascalString): Boolean;
|
|
var
|
|
i, L_: Integer;
|
|
sourChar, destChar: SystemChar;
|
|
begin
|
|
Result := False;
|
|
i := 1;
|
|
L_ := p^.Len;
|
|
if (Offset + L_ - 1) > Len then
|
|
Exit;
|
|
while i <= L_ do
|
|
begin
|
|
sourChar := GetChars(Offset + i - 1);
|
|
destChar := p^[i];
|
|
|
|
if CharIn(sourChar, cLoAtoZ) then
|
|
dec(sourChar, 32);
|
|
if CharIn(destChar, cLoAtoZ) then
|
|
dec(destChar, 32);
|
|
|
|
if sourChar <> destChar then
|
|
Exit;
|
|
inc(i);
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
function TPascalString.ComparePos(const Offset: Integer; const t: TPascalString): Boolean;
|
|
var
|
|
i, L_: Integer;
|
|
sourChar, destChar: SystemChar;
|
|
begin
|
|
Result := False;
|
|
i := 1;
|
|
L_ := t.Len;
|
|
if (Offset + L_) > Len then
|
|
Exit;
|
|
while i <= L_ do
|
|
begin
|
|
sourChar := GetChars(Offset + i - 1);
|
|
destChar := t[i];
|
|
|
|
if CharIn(sourChar, cLoAtoZ) then
|
|
dec(sourChar, 32);
|
|
if CharIn(destChar, cLoAtoZ) then
|
|
dec(destChar, 32);
|
|
|
|
if sourChar <> destChar then
|
|
Exit;
|
|
inc(i);
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
function TPascalString.GetPos(const s: TPascalString; const Offset: Integer = 1): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := 0;
|
|
if s.Len > 0 then
|
|
for i := Offset to Len - s.Len + 1 do
|
|
if ComparePos(i, @s) then
|
|
Exit(i);
|
|
end;
|
|
|
|
function TPascalString.GetPos(const s: PPascalString; const Offset: Integer = 1): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := 0;
|
|
if s^.Len > 0 then
|
|
for i := Offset to Len - s^.Len + 1 do
|
|
if ComparePos(i, s) then
|
|
Exit(i);
|
|
end;
|
|
|
|
function TPascalString.Exists(c: SystemChar): Boolean;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := low(buff) to high(buff) do
|
|
if buff[i] = c then
|
|
Exit(True);
|
|
Result := False;
|
|
end;
|
|
|
|
function TPascalString.Exists(c: array of SystemChar): Boolean;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := low(buff) to high(buff) do
|
|
if CharIn(buff[i], c) then
|
|
Exit(True);
|
|
Result := False;
|
|
end;
|
|
|
|
function TPascalString.Exists(const s: TPascalString): Boolean;
|
|
begin
|
|
Result := GetPos(@s, 1) > 0;
|
|
end;
|
|
|
|
function TPascalString.GetCharCount(c: SystemChar): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := 0;
|
|
for i := low(buff) to high(buff) do
|
|
if CharIn(buff[i], c) then
|
|
inc(Result);
|
|
end;
|
|
|
|
function TPascalString.hash: THash;
|
|
begin
|
|
Result := FastHashPPascalString(@Self);
|
|
end;
|
|
|
|
function TPascalString.Hash64: THash64;
|
|
begin
|
|
Result := FastHash64PPascalString(@Self);
|
|
end;
|
|
|
|
procedure TPascalString.DeleteLast;
|
|
begin
|
|
if Len > 0 then
|
|
SetLength(buff, length(buff) - 1);
|
|
end;
|
|
|
|
procedure TPascalString.DeleteFirst;
|
|
begin
|
|
if Len > 0 then
|
|
buff := System.Copy(buff, 1, Len);
|
|
end;
|
|
|
|
procedure TPascalString.Delete(idx, cnt: Integer);
|
|
begin
|
|
if (idx + cnt <= Len) then
|
|
Text := GetString(1, idx) + GetString(idx + cnt, Len + 1)
|
|
else
|
|
Text := GetString(1, idx);
|
|
end;
|
|
|
|
procedure TPascalString.Clear;
|
|
begin
|
|
SetLength(buff, 0);
|
|
end;
|
|
|
|
procedure TPascalString.Append(t: TPascalString);
|
|
var
|
|
r, L_: Integer;
|
|
begin
|
|
L_ := length(t.buff);
|
|
if L_ > 0 then
|
|
begin
|
|
r := length(buff);
|
|
SetLength(buff, r + L_);
|
|
CopyPtr(@t.buff[0], @buff[r], L_ * SystemCharSize);
|
|
end;
|
|
end;
|
|
|
|
procedure TPascalString.Append(c: SystemChar);
|
|
begin
|
|
SetLength(buff, length(buff) + 1);
|
|
buff[length(buff) - 1] := c;
|
|
end;
|
|
|
|
procedure TPascalString.Append(const Fmt: SystemString; const Args: array of const);
|
|
begin
|
|
Append(PFormat(Fmt, Args));
|
|
end;
|
|
|
|
function TPascalString.GetString(bPos, ePos: NativeInt): TPascalString;
|
|
begin
|
|
if ePos > length(buff) then
|
|
Result := Self.Copy(bPos, length(buff) - bPos + 1)
|
|
else
|
|
Result := Self.Copy(bPos, (ePos - bPos));
|
|
end;
|
|
|
|
procedure TPascalString.Insert(AText: SystemString; idx: Integer);
|
|
begin
|
|
Text := GetString(1, idx) + AText + GetString(idx + 1, Len);
|
|
end;
|
|
|
|
procedure TPascalString.FastAsText(var output: SystemString);
|
|
begin
|
|
SetLength(output, length(buff));
|
|
if length(buff) > 0 then
|
|
CopyPtr(@buff[0], @output[FirstCharPos], length(buff) * SystemCharSize);
|
|
end;
|
|
|
|
procedure TPascalString.FastGetBytes(var output: TBytes);
|
|
begin
|
|
{$IFDEF FPC}
|
|
output := SysUtils.TEncoding.UTF8.GetBytes(Text);
|
|
{$ELSE}
|
|
output := SysUtils.TEncoding.UTF8.GetBytes(buff);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function TPascalString.LowerText: SystemString;
|
|
begin
|
|
Result := LowerCase(Text);
|
|
end;
|
|
|
|
function TPascalString.UpperText: SystemString;
|
|
begin
|
|
Result := UpperCase(Text);
|
|
end;
|
|
|
|
function TPascalString.Invert: TPascalString;
|
|
var
|
|
i, j: Integer;
|
|
begin
|
|
SetLength(Result.buff, length(buff));
|
|
j := low(Result.buff);
|
|
for i := high(buff) downto low(buff) do
|
|
begin
|
|
Result.buff[j] := buff[i];
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.TrimChar(const Chars: TPascalString): TPascalString;
|
|
var
|
|
L_, bp, EP: Integer;
|
|
begin
|
|
Result := '';
|
|
L_ := Len;
|
|
if L_ > 0 then
|
|
begin
|
|
bp := 1;
|
|
while CharIn(GetChars(bp), @Chars) do
|
|
begin
|
|
inc(bp);
|
|
if (bp > L_) then
|
|
begin
|
|
Result := '';
|
|
Exit;
|
|
end;
|
|
end;
|
|
if bp > L_ then
|
|
Result := ''
|
|
else
|
|
begin
|
|
EP := L_;
|
|
|
|
while CharIn(GetChars(EP), @Chars) do
|
|
begin
|
|
dec(EP);
|
|
if (EP < 1) then
|
|
begin
|
|
Result := '';
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := GetString(bp, EP + 1);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TPascalString.DeleteChar(const Chars: TPascalString): TPascalString;
|
|
var
|
|
c: SystemChar;
|
|
begin
|
|
Result := '';
|
|
for c in buff do
|
|
if not CharIn(c, @Chars) then
|
|
Result.Append(c);
|
|
end;
|
|
|
|
function TPascalString.DeleteChar(const Chars: TOrdChars): TPascalString;
|
|
var
|
|
c: SystemChar;
|
|
begin
|
|
Result := '';
|
|
for c in buff do
|
|
if not CharIn(c, Chars) then
|
|
Result.Append(c);
|
|
end;
|
|
|
|
function TPascalString.ReplaceChar(const Chars: TPascalString; const newChar: SystemChar): TPascalString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result.Len := Len;
|
|
for i := low(buff) to high(buff) do
|
|
if CharIn(buff[i], Chars) then
|
|
Result.buff[i] := newChar
|
|
else
|
|
Result.buff[i] := buff[i];
|
|
end;
|
|
|
|
function TPascalString.ReplaceChar(const Chars, newChar: SystemChar): TPascalString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result.Len := Len;
|
|
for i := low(buff) to high(buff) do
|
|
if CharIn(buff[i], Chars) then
|
|
Result.buff[i] := newChar
|
|
else
|
|
Result.buff[i] := buff[i];
|
|
end;
|
|
|
|
function TPascalString.ReplaceChar(const Chars: TOrdChars; const newChar: SystemChar): TPascalString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result.Len := Len;
|
|
for i := low(buff) to high(buff) do
|
|
if CharIn(buff[i], Chars) then
|
|
Result.buff[i] := newChar
|
|
else
|
|
Result.buff[i] := buff[i];
|
|
end;
|
|
|
|
function TPascalString.BuildPlatformPChar: Pointer;
|
|
type
|
|
TAnsiChar_Buff = array [0 .. MaxInt - 1] of Byte;
|
|
PAnsiChar_Buff = ^TAnsiChar_Buff;
|
|
var
|
|
swap_buff: TBytes;
|
|
buff_P: PAnsiChar_Buff;
|
|
begin
|
|
swap_buff := PlatformBytes;
|
|
buff_P := GetMemory(length(swap_buff) + 1);
|
|
CopyPtr(@swap_buff[0], buff_P, length(swap_buff));
|
|
buff_P^[length(swap_buff)] := 0;
|
|
SetLength(swap_buff, 0);
|
|
Result := buff_P;
|
|
end;
|
|
|
|
class procedure TPascalString.FreePlatformPChar(p: Pointer);
|
|
begin
|
|
FreeMemory(p);
|
|
end;
|
|
|
|
class function TPascalString.RandomString(L_: Integer): TPascalString;
|
|
var
|
|
i: Integer;
|
|
rnd: TMT19937Random;
|
|
begin
|
|
Result.L := L_;
|
|
rnd := TMT19937Random.Create;
|
|
for i := 1 to L_ do
|
|
Result[i] := SystemChar(rnd.Rand32($7E - $20) + $20);
|
|
DisposeObject(rnd);
|
|
end;
|
|
|
|
function TPascalString.SmithWaterman(const p: PPascalString): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(@Self, @p);
|
|
end;
|
|
|
|
function TPascalString.SmithWaterman(const s: TPascalString): Double;
|
|
begin
|
|
Result := SmithWatermanCompare(@Self, @s);
|
|
end;
|
|
|
|
function TPascalString.BOMBytes: TBytes;
|
|
begin
|
|
{$IFDEF FPC}
|
|
Result := GetBytes;
|
|
{$ELSE}
|
|
Result := SysUtils.TEncoding.UTF8.GetPreamble + GetBytes;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
end.
|