📄 ststrl.pas
字号:
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 [edi+ebx], cl
dec cl
jnz @@MTNext
@@MTDone:
pop ebx { Restore registers }
pop esi
pop edi
end;
function BMSearchL(var Buffer; BufLength : Cardinal; var BT : BTable;
const MatchString : AnsiString ; var Pos : Cardinal) : Boolean; register;
{-Use the Boyer-Moore search method to search a buffer for a string.}
var
BufPtr : Pointer;
asm
push edi { Save registers since we will be changing }
push esi
push ebx
mov BufPtr, eax { Copy Buffer to local variable and ESI }
mov esi, MatchString { Set ESI to beginning of MatchString }
or esi, esi
jz @@BMSNotFound
mov edi, eax
mov ebx, ecx { Copy BT ptr to EBX }
mov ecx, edx { Length of buffer to ECX }
xor eax, eax { Zero EAX }
mov edx, [esi-StrOffset].LStrRec.Length
cmp edx, 0FFh { If EDX > 255, force to 255 }
jbe @@1
mov edx, 0FFh
@@1:
cmp dl, 1 { Check to see if we have a trivial case }
ja @@BMSInit { If Length(MatchString) > 1 do BM search }
jb @@BMSNotFound { If Length(MatchString) = 0 we're done }
mov al,[esi] { If Length(MatchString) = 1 do a REPNE SCASB }
mov ebx, edi
repne scasb
jne @@BMSNotFound { No match during REP SCASB }
mov esi, Pos { Set position in Pos }
{dec edi} { Found, calculate position }
sub edi, ebx
mov eax, 1 { Set result to True }
mov [esi], edi
jmp @@BMSDone { We're done }
@@BMSInit:
dec edx { Set up for BM Search }
add esi, edx { Set ESI to end of MatchString }
add ecx, edi { Set ECX to end of buffer }
add edi, edx { Set EDI to first check point }
std { Backward string ops }
mov dh, [esi] { Set DH to character we'll be looking for }
dec esi { Dec ESI in prep for BMSFound loop }
jmp @@BMSComp { Jump to first comparison }
@@BMSNext:
mov al, [ebx+eax] { Look up skip distance from table }
add edi, eax { Skip EDI ahead to next check point }
@@BMSComp:
cmp edi, ecx { Have we reached end of buffer? }
jae @@BMSNotFound { If so, we're done }
mov al, [edi] { Move character from buffer into AL for comparison }
cmp dh, al { Compare }
jne @@BMSNext { If not equal, go to next checkpoint }
push ecx { Save ECX }
dec edi
xor ecx, ecx { Zero ECX }
mov cl, dl { Move Length(MatchString) to ECX }
repe cmpsb { Compare MatchString to buffer }
je @@BMSFound { If equal, string is found }
mov al, dl { Move Length(MatchString) to AL }
sub al, cl { Calculate offset that string didn't match }
add esi, eax { Move ESI back to end of MatchString }
add edi, eax { Move EDI to pre-string compare location }
inc edi
mov al, dh { Move character back to AL }
pop ecx { Restore ECX }
jmp @@BMSNext { Do another compare }
@@BMSFound: { EDI points to start of match }
mov edx, BufPtr { Move pointer to buffer into EDX }
mov esi, Pos
sub edi, edx { Calculate position of match }
mov eax, edi
inc eax
inc eax
mov [esi], eax { Set Pos to position of match }
mov eax, 1 { Set result to True }
pop ecx { Restore ESP }
jmp @@BMSDone
@@BMSNotFound:
xor eax, eax { Set result to False }
@@BMSDone:
cld { Restore direction flag }
pop ebx { Restore registers }
pop esi
pop edi
end;
function BMSearchUCL(var Buffer; BufLength : Cardinal; var BT : BTable;
const MatchString : AnsiString ; var Pos : Cardinal) : Boolean; register;
{-Use the Boyer-Moore search method to search a buffer for a string. This
search is not case sensitive.}
var
BufPtr : Pointer;
asm
push edi { Save registers since we will be changing }
push esi
push ebx
mov BufPtr, eax { Copy Buffer to local variable and ESI }
mov esi, MatchString { Set ESI to beginning of MatchString }
or esi, esi
jz @@BMSNotFound
mov edi, eax
mov ebx, ecx { Copy BT ptr to EBX }
mov ecx, edx { Length of buffer to ECX }
xor eax, eax { Zero EAX }
mov edx, [esi-StrOffset].LStrRec.Length
cmp edx, 0FFh { If EDX > 255, force to 255 }
jbe @@1
mov edx, 0FFh
@@1:
or dl, dl { Check to see if we have a trivial case }
jz @@BMSNotFound { If Length(MatchString) = 0 we're done }
@@BMSInit:
dec edx { Set up for BM Search }
add esi, edx { Set ESI to end of MatchString }
add ecx, edi { Set ECX to end of buffer }
add edi, edx { Set EDI to first check point }
mov dh, [esi] { Set DH to character we'll be looking for }
dec esi { Dec ESI in prep for BMSFound loop }
jmp @@BMSComp { Jump to first comparison }
@@BMSNext:
mov al, [ebx+eax] { Look up skip distance from table }
add edi, eax { Skip EDI ahead to next check point }
@@BMSComp:
cmp edi, ecx { Have we reached end of buffer? }
jae @@BMSNotFound { If so, we're done }
push ebx { Save registers }
push ecx
push edx
mov al, [edi] { Move character from buffer into AL for comparison }
push eax { Push Char onto stack for CharUpper }
call CharUpper
pop edx { Restore registers }
pop ecx
pop ebx
cmp dh, al { Compare }
jne @@BMSNext { If not equal, go to next checkpoint }
push ecx { Save ECX }
dec edi
xor ecx, ecx { Zero ECX }
mov cl, dl { Move Length(MatchString) to ECX }
jecxz @@BMSFound { If ECX is zero, string is found }
@@StringComp:
xor eax, eax
mov al, [edi] { Get char from buffer }
dec edi { Dec buffer index }
push ebx { Save registers }
push ecx
push edx
push eax { Push Char onto stack for CharUpper }
call CharUpper
pop edx { Restore registers }
pop ecx
pop ebx
mov ah, al { Move buffer char to AH }
mov al, [esi] { Get MatchString char }
dec esi
cmp ah, al { Compare }
loope @@StringComp { OK? Get next character }
je @@BMSFound { Matched! }
xor ah, ah { Zero AH }
mov al, dl { Move Length(MatchString) to AL }
sub al, cl { Calculate offset that string didn't match }
add esi, eax { Move ESI back to end of MatchString }
add edi, eax { Move EDI to pre-string compare location }
inc edi
mov al, dh { Move character back to AL }
pop ecx { Restore ECX }
jmp @@BMSNext { Do another compare }
@@BMSFound: { EDI points to start of match }
mov edx, BufPtr { Move pointer to buffer into EDX }
mov esi, Pos
sub edi, edx { Calculate position of match }
mov eax, edi
inc eax
inc eax
mov [esi], eax { Set Pos to position of match }
mov eax, 1 { Set result to True }
pop ecx { Restore ESP }
jmp @@BMSDone
@@BMSNotFound:
xor eax, eax { Set result to False }
@@BMSDone:
pop ebx { Restore registers }
pop esi
pop edi
end;
{--------------- DOS pathname parsing -----------------}
function DefaultExtensionL(const Name, Ext : AnsiString) : AnsiString;
{-Return a file name with a default extension attached.}
var
DotPos : Cardinal;
begin
if HasExtensionL(Name, DotPos) then
Result := Name
else if Name = '' then
Result := ''
else
Result := Name + '.' + Ext;
end;
function ForceExtensionL(const Name, Ext : AnsiString) : AnsiString;
{-Force the specified extension onto the file name.}
var
DotPos : Cardinal;
begin
if HasExtensionL(Name, DotPos) then
Result := System.Copy(Name, 1, DotPos) + Ext
else if Name = '' then
Result := ''
else
Result := Name + '.' + Ext;
end;
function JustFilenameL(const PathName : AnsiString) : AnsiString;
{-Return just the filename and extension of a pathname.}
var
I : Cardinal;
begin
Result := '';
if PathName = '' then Exit;
I := Succ(Cardinal(Length(PathName)));
repeat
Dec(I);
until (I = 0) or (PathName[I] in DosDelimSet); {!!.01}
Result := System.Copy(PathName, Succ(I), StMaxFileLen);
end;
function JustNameL(const PathName : AnsiString) : AnsiString;
{-Return just the filename (no extension, path, or drive) of a pathname.}
var
DotPos : Cardinal;
S : AnsiString;
begin
S := JustFileNameL(PathName);
if HasExtensionL(S, DotPos) then
S := System.Copy(S, 1, DotPos-1);
Result := S;
end;
function JustExtensionL(const Name : AnsiString) : AnsiString;
{-Return just the extension of a pathname.}
var
DotPos : Cardinal;
begin
if HasExtensionL(Name, DotPos) then
Result := System.Copy(Name, Succ(DotPos), StMaxFileLen)
else
Result := '';
end;
function JustPathnameL(const PathName : AnsiString) : AnsiString;
{-Return just the drive and directory portion of a pathname.}
var
I : Cardinal;
begin
if PathName = '' then Exit;
I := Succ(Cardinal(Length(PathName)));
repeat
Dec(I);
until (I = 0) or (PathName[I] in DosDelimSet); {!!.01}
if I = 0 then
{Had no drive or directory name}
SetLength(Result, 0)
else if I = 1 then
{Either the root directory of default drive or invalid pathname}
Result := PathName[1]
else if (PathName[I] = '\') then begin
if PathName[Pred(I)] = ':' then
{Root directory of a drive, leave trailing backslash}
Result := System.Copy(PathName, 1, I)
else
{Subdirectory, remove the trailing backslash}
Result := System.Copy(PathName, 1, Pred(I));
end else
{Either the default directory of a drive or invalid pathname}
Result := System.Copy(PathName, 1, I);
end;
function AddBackSlashL(const DirName : AnsiString) : AnsiString;
{-Add a default backslash to a directory name}
begin
Result := DirName;
if (Length(Result) = 0) then
Exit;
if ((Length(Result) = 2) and (Result[2] = ':')) or
((Length(Result) > 2) and (Result[Length(Result)] <> '\')) then
Result := Result + '\';
end;
function CleanFileNameL(const FileName : AnsiString) : AnsiString;
{-Return filename with at most 8 chars of name and 3 of extension}
var
DotPos : Cardinal;
NameLen : Word;
begin
if HasExtensionL(FileName, DotPos) then begin
{Take the first 8 chars of name and first 3 chars of extension}
NameLen := Pred(DotPos);
if NameLen > 8 then
NameLen := 8;
Result := System.Copy(FileName, 1, NameLen)+System.Copy(FileName, DotPos, 4);
end else
{Take the first 8 chars of name}
Result := System.Copy(FileName, 1, 8);
end;
function CleanPathNameL(const PathName : AnsiString) : AnsiString;
{-Return a pathname cleaned up as DOS does it.}
var
I : Cardinal;
S : AnsiString;
begin
SetLength(Result, 0);
S := PathName;
I := Succ(Cardinal(Length(S)));
repeat
dec(I);
if I > 2 then
if (S[I] = '\') and (S[I-1] = '\') then
if (S[I-2] <> ':') then
System.Delete(S, I, 1);
until I <= 0;
I := Succ(Cardinal(Length(S)));
repeat
{Get the next directory or drive portion of pathname}
repeat
Dec(I);
until (I = 0) or (S[I] in DosDelimSet); {!!.02}
{Clean it up and prepend it to output string}
Result := CleanFileNameL(System.Copy(S, Succ(I), StMaxFileLen)) + Result;
if I > 0 then begin
Result := S[I] + Result;
System.Delete(S, I, 255);
end;
until I <= 0;
end;
function HasExtensionL(const Name : AnsiString; var DotPos : Cardinal) : Boolean;
{-Determine if a pathname contains an extension and, if so, return the
position of the dot in front of the extension.}
var
I : Cardinal;
begin
DotPos := 0;
for I := Length(Name) downto 1 do
if (Name[I] = '.') and (DotPos = 0) then
DotPos := I;
Result := (DotPos > 0)
and not CharExistsL(System.Copy(Name, Succ(DotPos), StMaxFileLen), '\');
end;
{------------------ Formatting routines --------------------}
function CommaizeChL(L : Longint; Ch : AnsiChar) : AnsiString;
{-Convert a long integer to a string with Ch in comma positions}
var
Temp : string;
NumCommas, I, Len : Cardinal;
Neg : Boolean;
begin
SetLength(Temp, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -