* Faster stringreplace (bug ID 26864)

git-svn-id: trunk@33055 -
This commit is contained in:
michael 2016-02-06 10:19:56 +00:00
parent dea4ac557d
commit cf530f117e
4 changed files with 94 additions and 0 deletions

View File

@ -1,3 +1,82 @@
var
OldPat,Srch: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
PatLength,NewPatLength,P,Cnt,PatCount,PrevP: Integer;
c,d: SRPChar ;
begin
PatLength:=Length(OldPattern);
if PatLength=0 then begin
Result:=S;
exit;
end;
if rfIgnoreCase in Flags then begin
Srch:=SRUpperCase(S);
OldPat:=SRUpperCase(OldPattern);
end else begin
Srch:=S;
OldPat:=OldPattern;
end;
PatLength:=Length(OldPat);
if Length(NewPattern)=PatLength then begin
//Result length will not change
Result:=S;
P:=1;
repeat
P:=Pos(OldPat,Srch,P);
if P>0 then begin
move(NewPattern[1],Result[P],PatLength);
if not (rfReplaceAll in Flags) then exit;
inc(P,PatLength);
end;
until p=0;
end else begin
//Different pattern length -> Result length will change
//To avoid creating a lot of temporary strings, we count how many
//replacements we're going to make.
P:=1; PatCount:=0;
repeat
P:=Pos(OldPat,Srch,P);
if P>0 then begin
inc(P,PatLength);
inc(PatCount);
if not (rfReplaceAll in Flags) then break;
end;
until p=0;
if PatCount=0 then begin
Result:=S;
exit;
end;
NewPatLength:=Length(NewPattern);
SetLength(Result,Length(S)+PatCount*(NewPatLength-PatLength)*SizeOf(SRChar));
P:=1; PrevP:=0;
c:=SRPChar(Result); d:=SRPChar(S);
repeat
P:=Pos(OldPat,Srch,P);
if P>0 then begin
Cnt:=P-PrevP-1;
if Cnt>0 then begin
Move(d^,c^,Cnt);
inc(c,Cnt);
inc(d,Cnt);
end;
if NewPatLength>0 then begin
Move(NewPattern[1],c^,NewPatLength);
inc(c,NewPatLength);
end;
inc(P,PatLength);
inc(d,PatLength);
PrevP:=P-1;
if not (rfReplaceAll in Flags) then break;
end;
until p=0;
Cnt:=Length(S)-PrevP;
if Cnt>0 then Move(d^,c^,Cnt);
end;
end;
(*
var
Srch,OldP,RemS: SRString; // Srch and Oldp can contain uppercase versions of S,OldPattern
P : Integer;
@ -34,3 +113,4 @@ begin
end;
end;
end;
*)

View File

@ -2628,6 +2628,8 @@ end;
{$define INSTRINGREPLACE}
{$define SRString:=String}
{$define SRUpperCase:=AnsiUppercase}
{$define SRPCHAR:=PChar}
{$define SRCHAR:=Char}
Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
{$i syssr.inc}
@ -2635,6 +2637,8 @@ Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplace
{$undef INSTRINGREPLACE}
{$undef SRString}
{$undef SRUpperCase}
{$undef SRPCHAR}
{$undef SRCHAR}
Function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;

View File

@ -537,9 +537,14 @@ end;
{$define INUNICODESTRINGREPLACE}
{$define SRString:=UnicodeString}
{$define SRUpperCase:=WideUppercase}
{$define SRPCHAR:=PChar}
{$define SRCHAR:=Char}
function UnicodeStringReplace(const S, OldPattern, NewPattern: UnicodeString; Flags: TReplaceFlags): UnicodeString;
{$i syssr.inc}
{$undef INUNICODESTRINGREPLACE}
{$undef SRString}
{$undef SRUpperCase}
{$undef SRPCHAR}
{$undef SRCHAR}

View File

@ -184,9 +184,14 @@ end;
{$define INWIDESTRINGREPLACE}
{$define SRString:=WideString}
{$define SRUpperCase:=WideUppercase}
{$define SRPChar:=PWideChar}
{$define SRChar:=WideChar}
function WideStringReplace(const S, OldPattern, NewPattern: WideString; Flags: TReplaceFlags): WideString;
{$i syssr.inc}
{$undef INWIDESTRINGREPLACE}
{$undef SRString}
{$undef SRUpperCase}
{$undef SRPChar}
{$undef SRChar}