提高FastReplace速度 (fStrRep.pas)[1]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 luckyjan 的 blog

{其实还可以在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).

本文关键:提高FastReplace速度 (fStrRep.pas)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top