我希望Pos()适合用于指定Source字符串中的边界,而不是让它在整个数据中执行搜索。
假设我有一个100个字符长的字符串,我想只在(unicode / utf8)字符串的第5个和第20个字符之间执行Pos。
代码应该改编自delphi中的ASM快速代码实现,并且显然避免将字符串的一部分预先复制到临时代码中,因为目的是使其更快。
我的情景:
我有一个多次访问的字符串,每次将其中的一部分复制到另一个时间字符串,然后在其上执行Pos。我希望每次都避免使用中间副本,而是在我指定的边界内执行Pos。
编辑:在新版本被视为重复后编辑的问题。
我仍然想要一个扩展当前XE3 FastCode程序集实现的解决方案,因为这符合我的目标。
答案 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。如果你愿意,可以投票。