Простая функция like (wildcard) сравнения строк
Код сравнения строк с учетом wildcard символов может быть очень простым при рекурсивной реализации без предварительного разбора маски в какие-либо промежуточные структуры. Ниже приведен код функции, реализующей подобное сравнение (используются Ansi-строки - для unicode придется немного переделать).
-
Этот код достаточно эффективен при анализе небольших строк. Очень хорошо подходит, например, для сравнения путей файловой системы и тп. В частности, скорость работы существенно лучше реализации стандартного модуля Masks.
-
Функции предусматривают сравнение символов как с учетом регистра, так и без.
-
Предусмотрен файловый набор wildcard ?* и аналогичный sql набор _%. Причем могут использоваться одновременно оба и по аналогии с sql like можно задать Esc-символ. Все флаги сравнения и Esc-символ пакуются в дополнительный параметр вызова Op: Word.
Недостаток - глубокая рекурсия при сравнении (не подходит для длиных строк). Так же в отличие от реализации модуля masks отсутствуют множества в масках.
const
// Опция сравнения по маске без учета регистра для Like
likeText = 256;
likeNoFile = 2048;
likeNoSQL = 4096;
function LikePtr(S, Mask: PChar; Op: Word): boolean;
function MskType: Integer;
begin
Result := 0;
case Mask^ of
'*': if likeNoFile and Op = 0 then Result := 2;
'?': if likeNoFile and Op = 0 then Result := 1;
'%': if likeNoSQL and Op = 0 then Result := 2;
'_': if likeNoSQL and Op = 0 then Result := 1;
else
if Mask^ = Char(Lo(Op)) then Result := 3;
end;
end;
begin
if Mask[0] = #0 then
Result := S[0] = Mask[0]
else begin
case MskType of
0: begin
Result := (S[0] = Mask[0]) or ((Op and likeText <> 0) and (AnsiStrLIComp(S, Mask, 1) = 0));
if Result and (S^ <> #0) then
Result := LikePtr(@S[1], @Mask[1], Op);
end;
1: if S^ <> #0 then
Result := LikePtr(@S[1], @Mask[1], Op)
else
Result := False;
2: Result := LikePtr(S, @Mask[1], Op) or ((S^ <> #0) and LikePtr(@S[1], Mask, Op));
3: Result := (S[0] = Mask[1]) and ((S^ <> #0) and LikePtr(@S[1], @Mask[2], Op));
else
Result := False;
end;
end;
end;
function Like(const S, Mask: String; Op: Word): boolean;
begin
Result := LikePtr(PChar(S), PChar(Mask), Op);
end;
|