📄 ststrs.pas
字号:
if S[I] = Quote then
InQuote := not InQuote;
Inc(I);
end
else begin
Pos := I;
Result := True;
end;
end;
end;
function ExtractAsciiS(N : Cardinal; const S, WordDelims : ShortString;
Quote : AnsiChar) : ShortString;
{-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
I : Cardinal;
Len : Byte;
SLen : Byte absolute S;
InQuote : Boolean;
begin
Len := 0;
InQuote := False;
if AsciiPositionS(N, S, WordDelims, Quote, I) then
{find the end of the current word}
while (I <= SLen) and ((InQuote) or not CharExistsS(WordDelims, S[I])) do begin
{add the I'th character to result}
Inc(Len);
if S[I] = Quote then
InQuote := not(InQuote);
Result [Len] := S[I];
Inc(I);
end;
Result [0] := Char(Len);
end;
procedure WordWrapS(const InSt : ShortString; var OutSt, Overlap : ShortString;
Margin : Cardinal; PadToMargin : Boolean);
{-Wrap a text string at a specified margin.}
var
EOS, BOS : Cardinal;
InStLen : Byte;
OutStLen : Byte absolute OutSt;
OvrLen : Byte absolute Overlap;
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}
OutStLen := EOS;
Move(InSt[1], OutSt[1], OutStLen);
{find the start of the next word in the line}
BOS := EOS+1;
while (BOS <= InStLen) and (InSt[BOS] = ' ') do
Inc(BOS);
if BOS > InStLen then
OvrLen := 0
else begin
{copy from the start of the next word to the end of the line}
OvrLen := Succ(InStLen-BOS);
Move(InSt[BOS], Overlap[1], OvrLen);
end;
{pad the end of the output string if requested}
if PadToMargin and (OutStLen < Margin) then begin
FillChar(OutSt[OutStLen+1], Margin-OutStLen, ' ');
OutStLen := Margin;
end;
end;
{--------------- String comparison and searching -----------------}
function CompStringS(const S1, S2 : ShortString) : Integer;
{-Compare two strings.}
register;
asm
push edi
mov edi, edx { EDI points to S2 }
push esi
mov esi, eax { ESI points to S1 }
xor ecx, ecx
mov dl, [edi] { DL = Length(S2) }
inc edi { EDI points to S2[1] }
mov cl, [esi]
inc esi { CL = Length(S1) - ESI points to S1[1] }
or eax, -1 { EAX holds temporary result }
cmp cl, dl { Compare lengths }
je @@EqLen { Lengths equal? }
jb @@Comp { Jump if S1 shorter than S1 }
inc eax { S1 longer than S2 }
mov cl, dl { 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 CompUCStringS(const S1, S2 : ShortString) : Integer;
{-Compare two strings. This compare is not case sensitive.}
register;
asm
push ebx
push edi { Save registers }
push esi
mov edi, edx { EDI points to S2 }
mov esi, eax { ESI points to S1 }
xor eax, eax { EAX holds chars from S1 }
xor ecx, ecx { ECX holds count of chars to compare }
xor edx, edx { DH holds temp result, DL chars from S2 }
or ebx, -1
mov al, [edi] { AH = Length(S2) }
inc edi { EDI points to S2[1] }
mov cl, [esi] { CL = Length(S1) - SI points to S1[1] }
inc esi
cmp cl, al { Compare lengths }
je @@EqLen { Lengths equal? }
jb @@Comp { Jump if S1 shorter than S1 }
inc ebx { S1 longer than S2 }
mov cl, al { Shorter length in CL }
@@EqLen:
inc ebx { Equal or greater }
@@Comp:
or ecx, ecx
jz @@Done { Done if lesser string is empty }
@@Start:
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 }
jnz @@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 AX }
pop esi { Restore Registers }
pop edi
pop ebx
end;
function SoundexS(const S : ShortString) : ShortString; assembler;
{-Return 4 character soundex of an input string}
register;
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);
asm
push edi
mov edi, edx { EDI => output string }
push ebx
push esi
mov esi, eax { ESI => input string }
mov byte ptr [edi], 4 { Prepare output string to be #4'0000' }
mov dword ptr [edi+1], '0000'
inc edi
mov cl, byte ptr [esi]
inc esi
or cl, cl { Exit if null string }
jz @@Done
xor eax, eax
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 cl { One input character used }
jz @@Done { Was input string one char long? }
mov ch, 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 ch { Decrement output counter }
jz @@Done { If zero, we're done }
mov bl, al { New previous character }
@@NoStore:
dec cl { Decrement input counter }
jnz @@Next
@@Done:
pop esi
pop ebx
pop edi
end;
function MakeLetterSetS(const S : ShortString) : Longint;
{-Return a bit-mapped long storing the individual letters contained in S.}
register;
asm
push ebx { Save registers }
push esi
mov esi, eax { ESI => string }
xor ecx, ecx { Zero ECX }
xor edx, edx { Zero EDX }
xor eax, eax { Zero EAX }
add cl, [esi] { CX = Length(S) }
jz @@Exit { Done if ECX is 0 }
inc esi
@@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 BMMakeTableS(const MatchString : ShortString; var BT : BTable);
{-Build a Boyer-Moore link table}
register;
asm
push edi { Save registers because they will be changed }
push esi
mov esi, eax { Move EAX to ESI }
push ebx
xor eax, eax { Zero EAX }
xor ecx, ecx { Zero ECX }
mov cl, [esi] { ECX has length of MatchString }
inc esi
mov ch, cl { Duplicate CL in CH }
mov eax, ecx { Fill each byte in EAX with length }
shl eax, 16
or eax, ecx
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
xor ebx, ebx { Zero EBX }
mov cl, al { Restore CL to length of string }
dec ecx
@@MTNext:
mov al, [esi] { Load table with positions of letters }
mov bl, al { that exist in the search string }
inc esi
mov [edx+ebx], cl
dec cl
jnz @@MTNext
@@MTDone:
pop ebx { Restore registers }
pop esi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -