You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 11 64位下FastPos()函数的等效替代方案咨询

Delphi 11 64位下兼容原FastPos()功能的实现方案

问题背景

将Delphi 6 32位代码迁移至Delphi 11 64位时,原依赖FastStrings.pas中的FastPos()因包含x86汇编代码无法编译,临时用Pos()替代但需要完全匹配原函数功能的64位实现(FastReplace()已通过StringReplace()替代并正常运行)。原FastPos()基于Boyer-Moore算法实现,核心特性包括:接受预计算的源串/查找串长度、支持起始查找位置、返回1-based匹配索引(无匹配返回0)。

兼容64位的纯Pascal实现

以下是完全复刻原FastPos()逻辑的纯Pascal实现,去掉了汇编代码,适配Delphi 11 64位环境:

1. 定义必要类型

type
  TBMJumpTable = array[Char] of Integer;

2. 实现Boyer-Moore跳转表构建函数

procedure MakeBMTable(const P: PChar; const Len: Integer; var JumpTable: TBMJumpTable);
var
  I: Integer;
begin
  // 初始化跳转表,默认跳转距离为查找串长度
  FillChar(JumpTable, SizeOf(JumpTable), Len);
  // 为查找串中每个字符设置对应跳转距离
  for I := 0 to Len - 2 do
    JumpTable[P[I]] := Len - I - 1;
end;

3. 实现Boyer-Moore查找核心函数

function BMPos(const Source, Find: PChar; const SourceLen, FindLen: Integer; const JumpTable: TBMJumpTable): PChar;
var
  SrcIdx, FindIdx: Integer;
begin
  Result := nil;
  if (SourceLen < FindLen) or (FindLen = 0) then Exit;

  SrcIdx := FindLen - 1;
  while SrcIdx < SourceLen do
  begin
    FindIdx := FindLen - 1;
    // 从字符串尾部向前匹配
    while (FindIdx >= 0) and (Source[SrcIdx] = Find[FindIdx]) do
    begin
      Dec(SrcIdx);
      Dec(FindIdx);
    end;
    if FindIdx < 0 then
    begin
      // 找到匹配,返回起始指针
      Result := @Source[SrcIdx + 1];
      Break;
    end;
    // 根据跳转表移动源串指针,取最大跳转距离避免回退
    Inc(SrcIdx, Max(JumpTable[Source[SrcIdx]], FindLen - FindIdx));
  end;
end;

4. 实现兼容原参数的FastPos函数

function FastPos(const aSourceString, aFindString: string; const aSourceLen, aFindLen, StartPos: Integer): Integer;
var
  JumpTable: TBMJumpTable;
  SourcePtr, FoundPtr: PChar;
  AdjustedSourceLen: Integer;
begin
  Assert(StartPos > 0);
  // 边界条件判断:查找串为空、查找串比源串长、起始位置超出源串范围
  if (aFindLen < 1) or (aFindLen > aSourceLen) or (StartPos > aSourceLen) then
  begin
    Result := 0;
    Exit;
  end;

  MakeBMTable(PChar(aFindString), aFindLen, JumpTable);
  SourcePtr := PChar(aSourceString) + (StartPos - 1);
  AdjustedSourceLen := aSourceLen - (StartPos - 1);
  FoundPtr := BMPos(SourcePtr, PChar(aFindString), AdjustedSourceLen, aFindLen, JumpTable);

  if Assigned(FoundPtr) then
    // 64位下用NativeInt处理指针转换,避免32位Integer截断指针
    Result := NativeInt(FoundPtr) - NativeInt(@aSourceString[1]) + 1
  else
    Result := 0;
end;

关键说明

  • 完全复刻原FastPos()的逻辑:基于Boyer-Moore算法、支持预传长度参数、保留起始位置参数、返回1-based索引(无匹配返回0)
  • 移除了x86汇编代码,纯Pascal实现可在Delphi 11 64位环境正常编译
  • 64位环境下使用NativeInt处理指针转换,避免原代码中Integer强制转换导致的指针截断问题
  • 保留原函数的Assert检查,确保StartPos参数合法性

简化替代方案(性能略低)

如果对性能要求不高,也可以基于Delphi自带的PosEx()封装,快速实现兼容原参数的函数:

function FastPos_Simple(const aSourceString, aFindString: string; const aSourceLen, aFindLen, StartPos: Integer): Integer;
begin
  Assert(StartPos > 0);
  if (aFindLen < 1) or (aFindLen > aSourceLen) or (StartPos > aSourceLen) then
  begin
    Result := 0;
    Exit;
  end;
  // 直接调用PosEx,匹配原函数的参数逻辑
  Result := PosEx(aFindString, aSourceString, StartPos);
end;

内容的提问来源于stack exchange,提问作者Question stack overflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:15:37