add backtracking irc glob matching
This commit is contained in:
parent
0921cb8086
commit
ab66df4d43
2 changed files with 46 additions and 2 deletions
|
@ -18,3 +18,37 @@ def _collapse(pattern: str) -> str:
|
|||
i += 1
|
||||
return out
|
||||
|
||||
def _match(pattern: str, s: str):
|
||||
i, j = 0, 0
|
||||
|
||||
i_backup = -1
|
||||
j_backup = -1
|
||||
while j < len(s):
|
||||
p = (pattern[i:] or [None])[0]
|
||||
|
||||
if p == "*":
|
||||
i += 1
|
||||
i_backup = i
|
||||
j_backup = j
|
||||
|
||||
elif p in ["?", s[j]]:
|
||||
i += 1
|
||||
j += 1
|
||||
|
||||
else:
|
||||
if i_backup == -1:
|
||||
return False
|
||||
else:
|
||||
j_backup += 1
|
||||
j = j_backup
|
||||
i = i_backup
|
||||
|
||||
return i == len(pattern)
|
||||
|
||||
class Glob(object):
|
||||
def __init__(self, pattern: str):
|
||||
self._pattern = pattern
|
||||
def match(self, s: str) -> bool:
|
||||
return _match(self._pattern, s)
|
||||
def compile(pattern: str):
|
||||
return Glob(_collapse(pattern))
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from re import compile
|
||||
from re import compile as re_compile
|
||||
from typing import Optional, Pattern
|
||||
from irctokens import Hostmask
|
||||
from ..interface import IMatchResponseParam, IMatchResponseHostmask, IServer
|
||||
from ..glob import Glob, compile as glob_compile
|
||||
from .. import formatting
|
||||
|
||||
class Any(IMatchResponseParam):
|
||||
|
@ -52,7 +53,7 @@ class Regex(IMatchResponseParam):
|
|||
self._pattern: Optional[Pattern] = None
|
||||
def match(self, server: IServer, arg: str) -> bool:
|
||||
if self._pattern is None:
|
||||
self._pattern = compile(self._value)
|
||||
self._pattern = re_compile(self._value)
|
||||
return bool(self._pattern.search(arg))
|
||||
|
||||
class Nickname(IMatchResponseHostmask):
|
||||
|
@ -67,3 +68,12 @@ class Nickname(IMatchResponseHostmask):
|
|||
if self._folded is None:
|
||||
self._folded = server.casefold(self._nickname)
|
||||
return self._folded == server.casefold(hostmask.nickname)
|
||||
|
||||
class Mask(IMatchResponseHostmask):
|
||||
def __init__(self, mask: str):
|
||||
self._mask = mask
|
||||
self._compiled = Optional[Glob]
|
||||
def match(self, server: IServer, hostmask: Hostmask):
|
||||
if self._compiled is None:
|
||||
self._compiled = glob_compile(self._mask)
|
||||
return self._compiled.match(str(hostmask))
|
||||
|
|
Loading…
Reference in a new issue