在utf8字符串边界内的Pos()

时间:2013-01-05 05:33:18

标签: delphi assembly

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

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

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

我的情景:

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

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

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

1 个答案:

答案 0 :(得分: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。如果你愿意,可以投票。