📄 ststrl.pas
字号:
else begin
Pos := I;
Result := True;
end;
end;
end;
function ExtractAsciiL(N : Cardinal; const S, WordDelims : AnsiString;
Quote : AnsiChar) : AnsiString;
{-Given an array of word delimiters, return the N'th word in a string. Any
text within Quote characters is counted as one word.}
var
C : Cardinal;
I, J : Longint;
InQuote : Boolean;
begin
InQuote := False;
if AsciiPositionL(N, S, WordDelims, Quote, C) then begin
I := C;
J := I;
{find the end of the current word}
while (I <= Length(S)) and ((InQuote)
or not CharExistsL(WordDelims, S[I])) do begin
if S[I] = Quote then
InQuote := not(InQuote);
Inc(I);
end;
SetLength(Result, I-J);
Move(S[J], Result[1], I-J);
end;
end;
procedure WordWrapL(const InSt : AnsiString; var OutSt, Overlap : AnsiString;
Margin : Cardinal; PadToMargin : Boolean);
{-Wrap a text string at a specified margin.}
var
InStLen : Cardinal;
EOS, BOS : Cardinal;
Len : Integer; {!!.02}
begin
InStLen := Length(InSt);
{!!.02 - Added }
{ handle empty string on input }
if InStLen = 0 then begin
OutSt := '';
Overlap := '';
Exit;
end;
{!!.02 - End Added }
{find the end of the output string}
if InStLen > Margin then begin
{find the end of the word at the margin, if any}
EOS := Margin;
while (EOS <= InStLen) and (InSt[EOS] <> ' ') do
Inc(EOS);
if EOS > InStLen then
EOS := InStLen;
{trim trailing blanks}
while (InSt[EOS] = ' ') and (EOS > 0) do
Dec(EOS);
if EOS > Margin then begin
{look for the space before the current word}
while (EOS > 0) and (InSt[EOS] <> ' ') do
Dec(EOS);
{if EOS = 0 then we can't wrap it}
if EOS = 0 then
EOS := Margin
else
{trim trailing blanks}
while (InSt[EOS] = ' ') and (EOS > 0) do
Dec(EOS);
end;
end else
EOS := InStLen;
{copy the unwrapped portion of the line}
SetLength(OutSt, EOS);
Move(InSt[1], OutSt[1], Length(OutSt));
{find the start of the next word in the line}
BOS := Succ(EOS);
while (BOS <= InStLen) and (InSt[BOS] = ' ') do
Inc(BOS);
if BOS > InStLen then
SetLength(OverLap, 0)
else begin
{copy from the start of the next word to the end of the line}
SetLength(OverLap, InStLen);
Move(InSt[BOS], Overlap[1], Succ(InStLen-BOS));
SetLength(OverLap, Succ(InStLen-BOS));
end;
{pad the end of the output string if requested}
{!!.02 - Rewritten}
Len := Length(OutSt);
if PadToMargin and (Len < LongInt(Margin)) then begin
SetLength(OutSt, Margin);
FillChar(OutSt[Succ(Len)], LongInt(Margin)-Length(OutSt), ' ');
end;
{!!.02 - End Rewritten}
end;
{--------------- String comparison and searching -----------------}
function CompStringL(const S1, S2 : AnsiString) : Integer; register;
{-Compare two strings.}
asm
push edi
mov edi, edx { EDI points to S2 }
push esi
mov esi, eax { ESI points to S1 }
xor edx, edx
xor ecx, ecx
or edi, edi
jz @@1
mov edx, [edi-StrOffset].LStrRec.Length
@@1:
or esi, esi
jz @@2
mov ecx, [esi-StrOffset].LStrRec.Length
@@2:
or eax, -1 { EAX holds temporary result }
cmp ecx, edx { Compare lengths }
je @@EqLen { Lengths equal? }
jb @@Comp { Jump if S1 shorter than S1 }
inc eax { S1 longer than S2 }
mov ecx, edx { Length(S2) in CL }
@@EqLen:
inc eax { Equal or greater }
@@Comp:
or ecx, ecx
jz @@Done { Done if either is empty }
repe cmpsb { Compare until no match or ECX = 0 }
je @@Done { If Equal, result ready based on length }
mov eax, 1
ja @@Done { S1 Greater? Return 1 }
or eax, -1 { Else S1 Less, Return -1 }
@@Done:
pop esi
pop edi
end;
function CompUCStringL(const S1, S2 : AnsiString) : Integer; register;
{-Compare two strings. This compare is not case sensitive.}
asm
push ebx { Save registers }
push edi
push esi
mov edi, edx { EDI points to S2 }
mov esi, eax { ESI points to S1 }
xor eax, eax
xor ecx, ecx
xor edx, edx { DL chars from S2 }
or ebx, -1
or edi, edi
jz @@1
mov eax, [edi-StrOffset].LStrRec.Length
@@1:
or esi, esi
jz @@2
mov ecx, [esi-StrOffset].LStrRec.Length
@@2:
cmp ecx, eax { Compare lengths }
je @@EqLen { Lengths equal? }
jb @@Comp { Jump if S1 shorter than S1 }
inc ebx { S1 longer than S2 }
mov ecx, eax { Shorter length in ECX }
@@EqLen:
inc ebx { Equal or greater }
@@Comp:
or ecx, ecx
jz @@Done { Done if lesser string is empty }
@@Start:
xor eax, eax { EAX holds chars from S1 }
mov al, [esi] { S1[?] into AL }
inc esi
push ecx { Save registers }
push edx
push eax { Push Char onto stack for CharUpper }
call CharUpper
pop edx { Restore registers }
pop ecx
mov dl, [edi] { S2[?] into DL }
inc edi { Point EDI to next char in S2 }
mov dh, al
mov al, dl
mov dl, dh
push ecx { Save registers }
push edx
push eax { Push Char onto stack for CharUpper }
call CharUpper
pop edx { Restore registers }
pop ecx
cmp dl, al { Compare until no match }
jne @@Output
dec ecx
jnz @@Start
je @@Done { If Equal, result ready based on length }
@@Output:
mov ebx, 1
ja @@Done { S1 Greater? Return 1 }
or ebx, -1 { Else S1 Less, Return -1 }
@@Done:
mov eax, ebx { Result into EAX }
pop esi { Restore Registers }
pop edi
pop ebx
end;
function SoundexL(const S : AnsiString) : AnsiString;
{-Return 4 character soundex of an input string}
const
SoundexTable : array[0..255] of Char =
(#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0,
{ A B C D E F G H I J K L M }
#0, '1', '2', '3', #0, '1', '2', #0, #0, '2', '2', '4', '5',
{ N O P Q R S T U V W X Y X }
'5', #0, '1', '2', '6', '2', '3', #0, '1', #0, '2', #0, '2',
#0, #0, #0, #0, #0, #0,
{ a b c d e f g h i j k l m }
#0, '1', '2', '3', #0, '1', '2', #0, #0, '2', '2', '4', '5',
{ n o p q r s t u v w x y x }
'5', #0, '1', '2', '6', '2', '3', #0, '1', #0, '2', #0, '2',
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
#0, #0, #0);
begin
if S = '' then Exit;
SetLength(Result, 4);
asm
push edi
mov edi, [Result] { EDI => output string. }
mov edi, [edi]
push ebx
push esi
mov esi, S { ESI => input string. }
mov dword ptr [edi], '0000' { Initialize output string to '0000'. }
xor eax, eax
mov [edi+4], al { Set null at end of string. }
mov ecx, [esi-StrOffset].LStrRec.Length
or ecx, ecx { Exit if null string. }
jz @@Done
mov al, [esi] { Get first character of input string. }
inc esi
push ecx { Save ECX across call to CharUpper. }
push eax { Push Char onto stack for CharUpper. }
call CharUpper { Uppercase AL. }
pop ecx { Restore saved register. }
mov [edi], al { Store first output character. }
inc edi
dec ecx { One input character used. }
jz @@Done { Was input string one char long?. }
mov bh, 03h { Output max 3 chars beyond first. }
mov edx, offset SoundexTable { EDX => Soundex table. }
xor eax, eax { Prepare for address calc. }
xor bl, bl { BL will be used to store 'previous char'. }
@@Next:
mov al, [esi] { Get next char in AL. }
inc esi
mov al, [edx+eax] { Get soundex code into AL. }
or al, al { Is AL zero? }
jz @@NoStore { If yes, skip this char. }
cmp bl, al { Is it the same as the previous stored char? }
je @@NoStore { If yes, skip this char. }
mov [edi], al { Store char to Dest. }
inc edi
dec bh { Decrement output counter. }
jz @@Done { If zero, we're done. }
mov bl, al { New previous character. }
@@NoStore:
dec ecx { Decrement input counter. }
jnz @@Next
@@Done:
pop esi
pop ebx
pop edi
end;
end;
function MakeLetterSetL(const S : AnsiString) : Longint; register;
{-Return a bit-mapped long storing the individual letters contained in S.}
asm
push ebx { Save registers }
push esi
mov esi, eax { ESI => string }
xor ecx, ecx { Zero ECX }
xor edx, edx { Zero EDX }
{or edx, edx}
or eax, eax
jz @@Exit
xor eax, eax { Zero EAX }
add ecx, [esi-StrOffset].LStrRec.Length
jz @@Exit { Done if ECX is 0 }
@@Next:
mov al, [esi] { EAX has next char in S }
inc esi
push ecx { Save registers }
push edx
push eax { Push Char onto stack for CharUpper }
call CharUpper
pop edx { Restore registers }
pop ecx
sub eax, 'A' { Convert to bit number }
cmp eax, 'Z'-'A' { Was char in range 'A'..'Z'? }
ja @@Skip { Skip it if not }
mov ebx, eax { Exchange EAX and ECX }
mov eax, ecx
mov ecx, ebx
ror edx, cl
or edx, 01h { Set appropriate bit }
rol edx, cl
mov ebx, eax { Exchange EAX and ECX }
mov eax, ecx
mov ecx, ebx
@@Skip:
dec ecx
jnz @@Next { Get next character }
@@Exit:
mov eax, edx { Move EDX to result }
pop esi { Restore registers }
pop ebx
end;
procedure BMMakeTableL(const MatchString : AnsiString; var BT : BTable); register;
{-Build a Boyer-Moore link table}
asm
push edi { Save registers because they will be changed }
push esi
mov esi, eax { Move EAX to ESI }
push ebx
or eax, eax
jz @@MTDone
xor eax, eax { Zero EAX }
mov ecx, [esi-StrOffset].LStrRec.Length
cmp ecx, 0FFh { If ECX > 255, force to 255 }
jbe @@1
mov ecx, 0FFh
@@1:
mov ch, cl { Duplicate CL in CH }
mov eax, ecx { Fill each byte in EAX with length }
shl eax, 16
mov ax, cx
mov edi, edx { Point to the table }
mov ecx, 64 { Fill table bytes with length }
rep stosd
cmp al, 1 { If length <= 1, we're done }
jbe @@MTDone
mov edi, edx { Reset EDI to beginning of table }
xor ebx, ebx { Zero EBX }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -