{其实还可以在fastreplace中先对findstr进行判断,如果
findstr完全是中文的话,直接可以在fastreplace中用
fastpos,这样可以提高速度。}
unit fstrrep;
interface
type
tfastposproc = function(
const asourcestring, afindstring : string;
const asourcelen, afindlen, startpos : integer
) : integer;
function fastreplace(
var asourcestring : string;
const afindstring, areplacestring : string;
casesensitive : boolean = false) : string;
function fastpos(
const asourcestring, afindstring : string;
const asourcelen, afindlen, startpos : integer
) : integer;
function fastposnocase(
const asourcestring, afindstring : string;
const asourcelen, afindlen, startpos : integer
) : integer;
implementation
// this type declaration will become apparent later.
//the first thing to note here is that i’m passing the sourcelength and findl
//ength. as neither source nor find will alter at any point during fastreplace
//, there’s no need to call the length subroutine each time!
function fastpos(
const asourcestring, afindstring : string;
const asourcelen, afindlen, startpos : integer
) : integer;
var
sourcelen : integer;
begin
// next, we determine how many bytes we need to
// scan to find the "start" of afindstring.
sourcelen := asourcelen;
sourcelen := sourcelen - afindlen;
if (startpos-1) > sourcelen then begin
result := 0;
exit;
end;
sourcelen := sourcelen - startpos;
sourcelen := sourcelen +2;
// the asm starts here.
asm
// delphi uses esi, edi, and ebx a lot,
// so we must preserve them.
push esi
push edi
push ebx
// get the address of sourcestring[1]
// and add (startpos-1).
// we do this for the purpose of finding
// the next occurrence, rather than
// always the first!
mov edi, asourcestring
add edi, startpos
dec edi
// get the address of afindstring.
mov esi, afindstring
// note how many bytes we need to
// look through in asourcestring
// to find afindstring.
mov ecx, sourcelen
// get the first char of afindstring;
// note how it is done outside of the
// main loop, as it never changes!
mov al, [esi]
// now the findfirstcharacter loop!
@scasb:
// get the value of the current
// character in asourcestring.
// this is equal to ah := edi^, that
// is what the [] are around [edi].
mov ah, [edi]
// compare this character with adeststring[1].
cmp ah,al
// if they're not equal we don't
// compare the strings.
jne @nextchar
// if they're equal, obviously we do!
@comparestrings:
// put the length of afindlen in ebx.
mov ebx, afindlen
// we dec ebx to point to the end of
// the string; that is, we don't want to
// add 1 if afindstring is 1 in length!
dec ebx
// add by shengquanhu
// if ebx is zero, then we've successfully
// compared each character; i.e. it's a match!
// it will be happened when afindlen=1
jz @endofmatch
//add end
//here’s another optimization tip. people at this point usually push esi and
//so on and then pop esi and so forth at the end–instead, i opted not to chan
//ge esi and so on at all. this saves lots of pushing and popping!
@comparenext:
// get afindstring character +
// afindstringlength (the last char).