case insensitive Pos
delphi, delphi-2010
Solution
This version of my previous answer works in both D2007 and D2010.
- In Delphi 2007 the `CharUpCaseTable` is 256 bytes
- In Delphi 2010 it is 128 KB (65535*2).
The reason is Char size. In the older version of Delphi my original code only supported the current locale character set at initialization. My `InsensPosEx` is about 4 times faster than your code. Certainly it is possible to go even faster, but we would lose simplicity.
type
TCharUpCaseTable = array [Char] of Char;
var
CharUpCaseTable: TCharUpCaseTable;
procedure InitCharUpCaseTable(var Table: TCharUpCaseTable);
var
n: cardinal;
begin
for n := 0 to Length(Table) - 1 do
Table[Char(n)] := Char(n);
CharUpperBuff(@Table, Length(Table));
end;
function InsensPosEx(const SubStr, S: string; Offset: Integer = 1): Integer;
var
n: Integer;
SubStrLength: Integer;
SLength: Integer;
label
Fail;
begin
Result := 0;
if S = '' then Exit;
if Offset <= 0 then Exit;
SubStrLength := Length(SubStr);
SLength := Length(s);
if SubStrLength > SLength then Exit;
Result := Offset;
while SubStrLength <= (SLength-Result+1) do
begin
for n := 1 to SubStrLength do
if CharUpCaseTable[SubStr[n]] <> CharUpCaseTable[s[Result+n-1]] then
goto Fail;
Exit;
Fail:
Inc(Result);
end;
Result := 0;
end;
//...
initialization
InitCharUpCaseTable({var}CharUpCaseTable);
Problem
Is there any comparable function like Pos that is not case-sensitive in D2010 (unicode)? I know I can use Pos(AnsiUpperCase(FindString), AnsiUpperCase(SourceString)) but that adds a lot of processing time by converting the strings to uppercase every time the function is called. For example, on a 1000000 loop, Pos takes 78ms while converting to uppercase takes 764ms. ``` str1 := 'dfkfkL%&/s"#<.676505'; for i := 0 to 1000000 do PosEx('#<.', str1, 1); // Takes 78ms for i := 0 to 1000000 do PosEx(AnsiUpperCase('#<.'), AnsiUpperCase(str1), 1); // Takes 764ms ``` I know that to improve the performance of this specific example I can convert the strings to uppercase first before the loop, but the reason why I'm looking to have a Pos-like function that is not case-sensitive is to replace one from FastStrings. All the strings I'll be using Pos for will be different so I will need to convert each and every one to uppercase. Is there any other function that might be faster than Pos + convert the strings to uppercase?