⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpattern.pas

📁 一个曾经热门的网络游戏RO查看GRF工具的源码
💻 PAS
字号:
{  Direct translation from gpattern.c from glib.   Copyright (C) 1995-1997, 1999  Peter Mattis, Red Hat, Inc.   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.   This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with this library; if not, write to the   Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  }unit GPattern;interfacetype  { keep enum and structure of gpattern.c and patterntest.c in sync }  GMatchType = (    G_MATCH_ALL,       // "*A?A*"    G_MATCH_ALL_TAIL,  // "*A?AA"    G_MATCH_HEAD,      // "AAAA*"    G_MATCH_TAIL,      // "*AAAA"    G_MATCH_EXACT,     // "AAAAA"    G_MATCH_LAST  );  GPatternSpec = Record    match_type    : GMatchType;    pattern_length: Cardinal;    min_length    : Cardinal;    pattern       : PChar;  end;  PGPatternSpec = ^GPatternSpec;function g_pattern_spec_new(pattern: PChar): PGPatternSpec;function g_pattern_match_string(pspec: PGPatternSpec; str: PChar): Boolean;procedure g_pattern_spec_free(pspec: PGPatternSpec);implementationuses  SysUtils;function Reverse(Str: Pchar; Len: Integer): PChar;var  NewStr: PChar;  i, j: Integer;begin  GetMem(NewStr, Len + 1);  j := 0;  for i := Len - 1 downto 0 do  begin      NewStr[i] := Str[j];      Inc(j);  end;  NewStr[Len] := #0;  Result := NewStr;end;function g_pattern_spec_new(pattern: PChar): PGPatternSpec;var  pspec: PGPatternSpec;  seen_joker, seen_wildcard, more_wildcards: Boolean;  hw_pos, tw_pos, hj_pos, tj_pos: Integer;  follows_wildcard: Boolean;  pending_jokers: Cardinal;  s: PChar;  d: PChar;  i: Cardinal;  tmp: PChar;begin  //seen_joker := False;  //seen_wildcard := False;  //more_wildcards := False;  hw_pos := -1;  tw_pos := -1;  hj_pos := -1;  tj_pos := -1;  follows_wildcard := False;  pending_jokers := 0;  // canonicalize pattern and collect necessary stats  GetMem(pspec, SizeOf(GPatternSpec));  pspec^.pattern_length := StrLen(pattern);  pspec^.min_length := 0;  GetMem(pspec^.pattern, pspec^.pattern_length + 1);  d := pspec^.pattern;  s := pattern;  i := 0;  while s[0] <> #0 do  begin      if s[0] = '*' then      begin	  if follows_wildcard then    // compress multiple wildcards          begin	      Dec(pspec^.pattern_length);	      Continue;          end;	  follows_wildcard := True;	  if hw_pos < 0 then              hw_pos := i;	  tw_pos := i;      end else if s[0] = '*' then      begin          Inc(pending_jokers);          Inc(pspec^.min_length);      end else      begin          while pending_jokers > 0 do          begin              d[0] := '?';              Inc(d);              if hj_pos < 0 then                  hj_pos := i;              tj_pos := i;              Dec(pending_jokers);              Inc(i);	  end;          follows_wildcard := FALSE;          Inc(pspec^.min_length);      end;      d[0] := s[0];      Inc(d);      Inc(s);      Inc(i);  end;  while pending_jokers > 0 do  begin      d[0] := '?';      Inc(d);      if hj_pos < 0 then;          hj_pos := i;      tj_pos := i;      Dec(pending_jokers);  end;  d[0] := #0;  //Inc(d);  seen_joker := hj_pos >= 0;  seen_wildcard := hw_pos >= 0;  more_wildcards := ((seen_wildcard) and (hw_pos <> tw_pos));  // special case sole head/tail wildcard or exact matches  if (not seen_joker) and (not more_wildcards) then  begin      if pspec^.pattern[0] = '*' then      begin          pspec^.match_type := G_MATCH_TAIL;          Dec(pspec^.pattern_length);          tmp := pspec^.pattern + 1;          StrMove(pspec^.pattern, tmp, pspec^.pattern_length);          pspec^.pattern[pspec^.pattern_length] := #0;          Result := pspec;          Exit;      end;      if (pspec^.pattern_length > 0) and         (pspec^.pattern[pspec^.pattern_length - 1] = '*') then      begin          pspec^.match_type := G_MATCH_HEAD;          Dec(pspec^.pattern_length);          pspec^.pattern[pspec^.pattern_length] := #0;          Result := pspec;          Exit;      end;      if not seen_wildcard then      begin          pspec^.match_type := G_MATCH_EXACT;          Result := pspec;          Exit;      end;  end;  // now just need to distinguish between head or tail match start  tw_pos := Integer(pspec^.pattern_length) - 1 - tw_pos;	// last pos to tail distance  tj_pos := Integer(pspec^.pattern_length) - 1 - tj_pos;	// last pos to tail distance  if seen_wildcard then  begin      if tw_pos > hw_pos then          pspec^.match_type := G_MATCH_ALL_TAIL      else          pspec^.match_type := G_MATCH_ALL;  end else // seen_joker  begin      if tj_pos > hj_pos then          pspec^.match_type := G_MATCH_ALL_TAIL      else          pspec^.match_type := G_MATCH_ALL;  end;  if pspec^.match_type = G_MATCH_ALL_TAIL then  begin    tmp := pspec^.pattern;    pspec^.pattern := Reverse(pspec^.pattern, pspec^.pattern_length);    FreeMem(tmp);  end;  Result := pspec;end;procedure g_pattern_spec_free(pspec: PGPatternSpec);begin  if not Assigned(pspec) then Exit;  FreeMem(pspec^.pattern);  FreeMem(pspec);end;function g_pattern_ph_match (const match_pattern: PChar; const match_string: PChar): Boolean;var  pattern, str: PChar;  ch: Char;begin  pattern := match_pattern;  str := match_string;  ch := pattern[0];  Inc(pattern);  while ch <> #0 do  begin      case ch of        '?':        begin            if str[0] = #0 then            begin                Result := False;                Exit;            end;            Inc(str);        end;        '*':        begin            repeat            begin                ch := pattern[0];                Inc(pattern);                if ch = '?' then                begin                    if str = #0 then                    begin                        Result := False;                        Exit;                    end;                    Inc(str);                end;            end until (ch <> '*') and (ch <> '?');            if ch = #0 then            begin                Result := True;                Exit;            end;            repeat            begin                while ch <> str[0] do                begin                    if str[0] = #0 then                    begin                        Result := False;                        Exit;                    end;                    Inc(str);                end;                Inc(str);                if g_pattern_ph_match(pattern, str) then                begin                    Result := True;                    Exit;                end;            end until str[0] = #0;        end;        else        begin            if ch = str[0] then                Inc(str)            else            begin                Result := False;                Exit;            end;        end;      end;      ch := pattern[0];      Inc(pattern);  end;  Result := str[0] = #0;end;function g_pattern_match(pspec: PGPatternSpec; string_length: Cardinal; str: PChar; string_reversed: PChar): Boolean;var  tmp: PChar;begin  Result := False;  if not Assigned(pspec) then Exit;  if not Assigned(str) then Exit;  if (pspec^.min_length > string_length) then Exit;  case pspec^.match_type of    G_MATCH_ALL:    begin        Result := g_pattern_ph_match(pspec^.pattern, str);        Exit;    end;    G_MATCH_ALL_TAIL:    begin        if Assigned(string_reversed) then        begin            Result := g_pattern_ph_match(pspec^.pattern, string_reversed);            Exit;        end else        begin            tmp := Reverse(str, string_length);            Result := g_pattern_ph_match(pspec^.pattern, tmp);            FreeMem(tmp);            Exit;        end;    end;    G_MATCH_HEAD:    begin        if pspec^.pattern_length = string_length then            Result := String(pspec^.pattern) = String(str)        else if pspec^.pattern_length > 0 then            Result := StrLComp(pspec^.pattern, str, pspec^.pattern_length) = 0        else            Result := True;        Exit;    end;    G_MATCH_TAIL:    begin        tmp := str + (string_length - pspec^.pattern_length);        if pspec^.pattern_length > 0 then            Result := String(pspec^.pattern) = String(tmp)        else            Result := True;        Exit;    end;    G_MATCH_EXACT:    begin        if pspec^.pattern_length <> string_length then	    Result := False        else            Result := String(pspec^.pattern) = String(str);    end    else        Exit;  end;end;function g_pattern_match_string(pspec: PGPatternSpec; str: PChar): Boolean;begin  Result := g_pattern_match(pspec, StrLen(Str), Str, nil);end;end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -