在分析过程中,我遇到了一个需要花费大量时间的函数,但基本上可以归结为这段非常简单的代码:
function GetSubstring(AInput: PChar; AStart, ASubstringLength: Integer): string;
begin
Result := Copy(AInput, AStart, ASubstringLength);
end;
此函数返回预期的子字符串,但对于较长的输入它不能很好地扩展。我在 CPU 视图中查看了汇编代码,据我所知(我通常不在汇编级别工作),似乎AInput
在调用Copy
.
但是由于此时字符串/字符数组的长度是未知的,因此转换代码必须遍历 的长度,PChar
直到找到空终止符。这可以解释较长输入的可怕缩放。
但是,由于调用者传入了 的长度PChar
,我最初认为可以将方法转换为使用SetString
。
function GetSubstring(AInput: PChar; AStart, ASubstringLength: Integer): string;
begin
SetString(Result, AInput + AStart - 1, ASubstringLength);
end;
除了SetString
从零开始工作(不是从一开始的复制),在验证其输入方面似乎还有许多其他的小事情Copy
,并非所有这些都记录在案(例如,任何小于 1 的起始值都会被更改到 1)。所以上面的幼稚实现并不总是像原来的那样工作。
我的目标是尽可能多地复制该Copy
例程,因为此函数是库的一部分,并且已被我的同事广泛使用。
我想知道以下实现是否实现了这一点,或者我是否需要了解Copy
. 注意:FLength
实际长度AInput
来自该函数所属模块的另一部分。我为这个例子删除了其他部分。
function GetSubstring(AInput: PChar; AStart, ASubstringLength: Integer): string;
begin
if (AInput = nil) then begin
Result := '';
end else begin
if (AStart < 1) then begin
AStart := 0;
end else begin
AStart := AStart - 1;
end;
if (ASubstringLength + AStart > FLength) then begin
ASubstringLength := FLength - AStart;
end;
SetString(Result, AInput + AStart, ASubstringLength);
end;
end;
我使用的是 Delphi 2006,但我认为这在产品的其他版本(至少非 Unicode 版本)中并没有太大的不同。