diff --git a/components/lazutils/laz2_xmlutils.pas b/components/lazutils/laz2_xmlutils.pas index 88318a057d..e6c27a876d 100644 --- a/components/lazutils/laz2_xmlutils.pas +++ b/components/lazutils/laz2_xmlutils.pas @@ -548,6 +548,55 @@ var Result:=nil; end; + procedure ReplaceMultiByteWithResize(List: PItem; ListLen: SizeInt; Src: PChar); + var + c: Char; + clen: Integer; + NewSIndex, i: SizeInt; + Item: PItem; + NewS: string; + NewSP: PChar; + NewCharLen: Integer; + NewCharP: PChar; + begin + SetLength(NewS,length(s)); + NewSIndex:=Src-PChar(s)+1; + if NewSIndex>1 then + Move(s[1],NewS[1],NewSIndex-1); + while true do begin + c:=Src^; + if (c=#0) and (Src-PChar(s)=length(s)) then break; + clen:=UTF8CharacterLength(Src); + NewCharP:=Src; + NewCharLen:=clen; + // do a quick test via Pos + i:=Pos(c,SrcChars); + if i>0 then begin + // quick test positive, now search correctly + Item:=FindItem(List,ListLen,Src,clen); + if Item<>nil then begin + // replace + NewCharP:=@Item^.Dst[0]; + NewCharLen:=Item^.DstLen; + end; + end; + inc(Src,clen); + if NewSIndex+NewCharLen-1>length(NewS) then begin + // need more space => grow + SetLength(NewS,NewSIndex+((length(NewS)-NewSIndex-NewCharLen)*3 div 2)+2); + end; + // copy character + NewSP:=@NewS[NewSIndex]; + for i:=1 to NewCharLen do begin + NewSP^:=NewCharP^; + inc(NewCharP); + inc(NewSP); + end; + inc(NewSIndex,NewCharLen); + end; + s:=LeftStr(NewS,NewSIndex-1); + end; + procedure ReplaceMultiByte; var p: PChar; @@ -579,7 +628,10 @@ var Move(Item^.Dst[0],p^,clen); end else begin // replace with different size - // ToDo + // all following characters are moved + // => use an optimized algorithm for this + ReplaceMultiByteWithResize(List,ListLen,p); + exit; end; end; end; diff --git a/test/lazutils/testlazxml.pas b/test/lazutils/testlazxml.pas index 6ffdcac2b4..eba1931b86 100644 --- a/test/lazutils/testlazxml.pas +++ b/test/lazutils/testlazxml.pas @@ -79,9 +79,11 @@ begin T('switch a,b','abaa','ab','ba','babb'); T('delete a','a','a','',''); T('delete a','aba','a','','b'); - //T('replace ä with ö','bä','ä','ö','bö'); - //T('replace ä with ö','äbä','ä','ö','öbö'); + T('replace ä with ö','bä','ä','ö','bö'); + T('replace ä with ö','äbä','ä','ö','öbö'); T('switch ä,ö','äbö','äö','öä','öbä'); + T('delete ä','äbö','ä','','bö'); + T('replace ä with a','äbö','ä','a','abö'); end; initialization