|
{其实还可以在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). mov Al, [ESI+EBX] // Get aSourceString character (current // position + aFindStringLength). mov Ah, [EDI+EBX] // Compare them. cmp Al, Ah Jz @Matches // If they don''''t match, we put the first char // of aFindString into Al again to continue // looking for the first character. Mov Al, [ESI] Jmp @NextChar @Matches: // If they match, we DEC EBX (point to // previous character to compare). Dec EBX // If EBX <> 0 ("J"ump "N"ot "Z"ero), we // continue comparing strings. Jnz @CompareNext
//add by Shengquanhu @EndOfMatch: //add end
// If EBX is zero, then we''''ve successfully // compared each character; i.e. it''''s A MATCH! // Move the address of the *current* // character in EDI. // Note, we haven''''t altered EDI since // the first char was found. mov EAX, EDI // This is an address, so subtract the // address of aSourceString[1] to get // an actual character position. sub EAX, aSourceString // Inc EAX to make it 1-based, // rather than 0-based. inc EAX // Put it into result. mov Result, EAX // Finish this routine! jmp @TheEnd @NextChar: //This is where I jump to when I want to continue searching for the first char //acter of aFindString in aSearchString: // Point EDI (aFindString[X]) to // the next character. Inc EDI // Dec ECX tells us that we''''ve checked // another character, and that we''''re // fast running out of string to check! dec ECX // If EBX <> 0, then continue scanning // for the first character.
//add by shengquanhu //if ah is chinese char,jump again jz @Result0 cmp ah, $80 jb @ScaSB Inc EDI Dec ECX //add by shengquanhu end
jnz @ScaSB
//add by shengquanhu @Result0: //add by shengquanhu end
// If EBX = 0, then move 0 into RESULT. mov Result,0 // Restore EBX, EDI, ESI for Delphi // to work correctly. // Note that they''''re POPped in the // opposite order they were PUSHed. @TheEnd: pop EBX pop EDI pop ESI end; end;
//This routine is an identical copy of FastPOS except where commented! The ide //a is that when grabbing bytes, it ANDs them with $df, effectively making the //m lowercase before comparing. Maybe this would be quicker if aFindString was // made lowercase in one fell swoop at the beginning of the function, saving a //n AND instruction each time. function FastPosNoCase( const aSourceString, aFindString : String; const aSourceLen, aFindLen, StartPos : integer ) : integer; var SourceLen : integer; begin SourceLen := aSourceLen; SourceLen := SourceLen - aFindLen; if (StartPos-1) > SourceLen then begin Result := 0; Exit; end; SourceLen := SourceLen - StartPos; SourceLen := SourceLen +2; asm push ESI push EDI push EBX
mov EDI, aSourceString add EDI, StartPos Dec EDI &nbs [1] [2] [3] 下一页 [Delphi程序]转贴:Conversion to Delphi 6: Missing unit Pro… [Delphi程序]AXScript.pas,从官方站点找到的IActivsScript接口 [Delphi程序]lua头文件的pas翻译_lua.h
|