0

我希望有一个 Pos() 适合用于指定 Source 字符串中的边界,而不是让它在整个数据中执行搜索。

假设我有一个 100 个字符长的字符串,我只想在 (unicode/utf8) 字符串的第 5 和第 20 个字符之间执行 Pos。

代码应该改编自 delphi 中的 ASM 快速代码实现,并且显然避免将字符串的一部分预先复制到临时的,因为目的是让它比这更快。

我的场景:

我有一个被多次访问的字符串,每次,它的一部分被复制到另一个时间字符串,然后对其执行 Pos。我想每次都避免中间副本,而是在我指定的边界内执行 Pos。

编辑:在新问题被视为重复后编辑的问题。

我仍然想要一个扩展当前 XE3 FastCode 程序集实现的解决方案,因为这符合我的目标。

4

1 回答 1

1

这是一个不基于 asm 的替代方案。它也适用于 64 位应用程序。

function PosExUBound(const SubStr, Str: UnicodeString; Offset,EndPos: Integer): Integer; overload;
var
  I, LIterCnt, L, J: NativeInt;
  PSubStr, PS: PWideChar;
begin
  L := Length(SubStr);
  if (EndPos > Length(Str)) then
    EndPos := Length(Str);
  { Calculate the number of possible iterations. Not valid if Offset < 1. }

  LIterCnt := EndPos - 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 := PWideChar(SubStr);
    PS := PWideChar(Str);
    Inc(PS, Offset - 1);

    Dec(L);
    I := 0;
    J := L;
    repeat
      if PS[I + J] <> PSubStr[J] then
      begin
        Inc(I);
        J := L;
        Dec(LIterCnt);
        if (LIterCnt < 0)
          then Exit(0);
      end
      else
      if (J > 0) then
        Dec(J)
      else
        Exit(I + Offset);
    until false;
  end;

  Result := 0;
end;

我将把它作为练习来实现AnsiString重载版本。


顺便说一句,XE3 中的purepascal部分功能写得有点糟糕。Pos()请参阅QC111103 Inefficient loop in Pos() for purepascal。喜欢就给它投票吧。

于 2013-01-05T16:07:55.093 回答