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
相关产品推荐
相关产品推荐

