26.05.2010

Простая функция like (wildcard) сравнения строк

Код сравнения строк с учетом wildcard символов может быть очень простым при рекурсивной реализации без предварительного разбора маски в какие-либо промежуточные структуры. Ниже приведен код функции, реализующей подобное сравнение.

Недостаток - глубокая рекурсия при сравнении (не подходит для длиных строк). Так же в отличие от реализации модуля 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;
 

Hosted by uCoz