Проекты Логинова Дмитрия | ||||||||||
|
FastStringReplace - Fast String Replace - функция для быстрой замены строкВерсия от 07.01.2010 Иногда возникает необходимость в такой функции. Стандартная функция StringReplace() в большинстве случаев устраивает, однако при обработке больших строк эта функция является источником сильних тормозов. До недавнего времени не было никакой проблемы найти быстрый аналог в интернете. Однако в Delphi 2009 и 2010 из-за юникодных строк большая часть аналогов перестала работать. Поиски не увенчались успехом. Пришлось делать свой аналог. Функция FastStringReplace() работает точно также, как и StringReplace, поддерживаются все режимы. Разница только в скорости. В моей задаче скорость благодаря FastStringReplace() выросла в несколько сотен раз. Привожу исходный текст данной функции: function FastStringReplace(const S: string; OldPattern: string; const NewPattern: string; Flags: TReplaceFlags = [rfReplaceAll]): string; var I, J, Idx: Integer; IsEqual: Boolean; UpperFindStr: string; pS: PChar; // Указатель на массив для сравнения символов CanReplace: Boolean; begin if OldPattern = '' then begin Result := S; Exit; end; Result := ''; if S = '' then Exit; if rfIgnoreCase in Flags then begin OldPattern := AnsiUpperCase(OldPattern); // Для режима "не учитывать регистр" // потребуется дополнительная строка UpperFindStr := AnsiUpperCase(S); pS := PChar(UpperFindStr); end else pS := PChar(S); // Если новая подстрока не превышает старой, то... if Length(OldPattern) >= Length(NewPattern) then begin SetLength(Result, Length(S)); end else // Точный размер буфера не известен... SetLength(Result, (Length(S) + Length(OldPattern) + Length(NewPattern)) * 2); I := 1; Idx := 0; CanReplace := True; while I <= Length(S) do begin IsEqual := False; if CanReplace then // Если замена разрешена begin // Если I-й символ совпадает с OldPattern[1] if pS[I - 1] = OldPattern[1] then // Запускаем цикл поиска begin IsEqual := True; for J := 2 to Length(OldPattern) do begin if pS[I + J - 2] <> OldPattern[J] then begin IsEqual := False; Break; // Прерываем внутренний цикл end; end; // Совпадение найдено! Выполняем замену if IsEqual then begin for J := 1 to Length(NewPattern) do begin Inc(Idx); // Расширяем строку Result при необходимости if Idx > Length(Result) then SetLength(Result, Length(Result) * 2); Result[Idx] := NewPattern[J]; end; // Пропускаем байты в исходной строке Inc(I, Length(OldPattern)); if not (rfReplaceAll in Flags) then CanReplace := False; // Запрещаем дальнейшую замену end; end; end; // Если подстрока не найдена, то просто копируем символ if not IsEqual then begin Inc(Idx); // Расширяем строку Result при необходимости if Idx > Length(Result) then SetLength(Result, Length(Result) * 2); Result[Idx] := S[I]; Inc(I); end; end; // while I <= Length(S) do // Ограничиваем длину строки-результата SetLength(Result, Idx); end; | |||||||||
Логинов Дмитрий © 2005-2015 |