Title: return the position of the last occurence of a substring in String?
{1.}
{
Letzte Position von SubStr in S ermitteln.
Returns the last occurence of SubStr in S.
}
function LastPos(SubStr, S: string): Integer;
var
Found, Len, Pos: integer;
begin
Pos := Length(S);
Len := Length(SubStr);
Found := 0;
while (Pos 0) and (Found = 0) do
begin
if Copy(S, Pos, Len) = SubStr then
Found := Pos;
Dec(Pos);
end;
LastPos := Found;
end;
{*************************************************************}
// by Manuel Wiersch
{2.}
function LastPos(const SubStr: AnsiString; const S: AnsiString): LongInt;
asm
TEST EAX,EAX // EAX auf 0 prüfen (d.h. SubStr = nil)
JE @@noWork // wenn EAX = 0 dann Sprung zu noWork
TEST EDX,EDX
// Test ob S = nil
JE @@stringEmpty // bei Erfolg - Sprung zum Label 'stringEmpty'
PUSH EBX
PUSH ESI
PUSH EDI // Register auf dem Stack sichern Grund: OH
// OH: "In einer asm-Anweisung muß der Inhalt
// der Register EDI, ESI, ESP, EBP und EBX
// erhalten bleiben (dh. vorher auf dem Stack
// speichern) MOV ESI, EAX
// ESI = Sourceindex - Adresse vom SubStr
MOV EDI, EDX // EDI = Destinationindex - Adresse von S
MOV ECX,[EDI-4] // Länge von S ins Zählregister
MOV EDX,[ESI-4] // Länge des SubStr in EDX
DEC EDX // Length(SubStr) - 1
JS @@fail
// Vorzeichenbedingter Sprung (JumpIfSign)
// d.h. (EDX Sprung zu 'fail'
STD; // SetDirectionFlag - Stringroutinen von hinten
// abarbeiten
ADD ESI, EDX // Pointer auf das letzte Zeichen vom SubStr
ADD EDI, ECX
DEC EDI // Pointer auf das letzte Zeichen von S
MOV AL, [ESI] // letztes Zeichen des SubStr in AL laden
DEC ESI // Pointer auf das vorletzte Zeichen setzen.
SUB ECX, EDX // Anzahl der Stringdurchläufe
// = Length(s) - Length(substr) + 1
JLE @@fail // Sprung zu 'fail' wenn ECX
@@loop:
REPNE SCASB // Wdh. solange ungleich (repeat while not equal)
// scan string for byte
JNE @@fail
MOV EBX,ECX { Zähleregister, ESI und EDI sichern, da nun der
Vergleich durchgeführt wird ob die nachfolgenden
Zeichen von SubStr in S vorhanden sind }
PUSH ESI
PUSH EDI
MOV ECX,EDX // Länge des SubStrings in ECX
REPE CMPSB // Solange (ECX 0) und (Compare string fo byte)
// dh. solange S[i] = SubStr[i]
POP EDI
POP ESI // alten Source- und Destinationpointer vom Stack holen
JE @@found // Und schon haben wir den Index da ECX = 0
// dh. alle Zeichen wurden gefunden
MOV ECX, EBX // ECX wieder auf alte Anzahl setzen und
JMP @@loop // Start bei 'loop'
@@fail:
XOR EAX,EAX // EAX auf 0 setzen
JMP @@exit @@stringEmpty:
XOR EAX,EAX
JMP @@noWork @@found:
MOV EAX, EBX // in EBX steht nun der aktuelle Index
INC EAX // um 1 erhöhen, um die Position des 1. Zeichens zu
// bekommen
@@exit:
POP EDI
POP ESI
POP EBX
@@noWork: CLD; // DirectionFlag löschen
end;