function PosX(const SubStr, Str: string; Offset: Integer): Integer;
var
I, LIterCnt, L, J: Integer;
PSubStr, PS: PChar;
begin
L := Length(SubStr);
{ Calculate the number of possible iterations. Not valid if Offset < 1. }
LIterCnt := Length(Str) - Offset - L + 1;
{ Only continue if the number of iterations is positive or zero (there is space to check) }
if (Offset > 0) and (LIterCnt >= 0) and (L > 0) then
begin
PSubStr := PChar(SubStr);
PS := PChar(Str);
Inc(PS, Offset - 1);
for I := 0 to LIterCnt do
begin
J := 0;
while (J >= 0) and (J < L) do
begin
if UpCase(PS[I + J]) = UpCase(PSubStr[J]) then
Inc(J)
else
J := -1;
end;
if J >= L then
Exit(I + Offset);
end;
end;
Result := 0;
end;
function StringReplaceEx(const st, oldSubstr, newSubStr: string): string;
var
idx, len: Integer;
iStart: Integer;
sb: TStringBuilder;
begin
len := Length(oldSubstr);
iStart := 1;
sb := TStringBuilder.Create;
try
repeat
idx := posX(oldSubstr, st, iStart);
if idx > 0 then
begin
sb.Append(Copy(st, iStart, idx - iStart));
sb.Append(newSubStr);
iStart := idx + len;
end;
until idx <= 0;
sb.Append(Copy(st, iStart, length(st)));
Result := sb.ToString;
finally
sb.Free;
end;
end;