#!/usr/bin/env python3# SPDX-License-Identifier: GPL-2.0# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>."""Regular expression ancillary classes.Those help caching regular expressions and do matching for kernel-doc."""import re# Local cache for regular expressionsre_cache = {}class KernRe: """ Helper class to simplify regex declaration and usage. It calls re.compile for a given pattern. It also allows adding regular expressions and define sub at class init time. Regular expressions can be cached via an argument, helping to speedup searches. """ def _add_regex(self, string, flags): """ Adds a new regex or reuses it from the cache. """ self.regex = re_cache.get(string, None) if not self.regex: self.regex = re.compile(string, flags=flags) if self.cache: re_cache[string] = self.regex def __init__(self, string, cache=True, flags=0): """ Compile a regular expression and initialize internal vars. """ self.cache = cache self.last_match = None self._add_regex(string, flags) def __str__(self): """ Return the regular expression pattern. """ return self.regex.pattern def __repr__(self): """ Returns a displayable version of the class init. """ flag_map = { re.IGNORECASE: "re.I", re.MULTILINE: "re.M", re.DOTALL: "re.S", re.VERBOSE: "re.X", } flags = [] for flag, name in flag_map.items(): if self.regex.flags & flag: flags.append(name) flags_name = " | ".join(flags) max_len = 60 pattern = "" for pos in range(0, len(self.regex.pattern), max_len): pattern += '"' + self.regex.pattern[pos:max_len + pos] + '" ' if flags_name: return f'KernRe({pattern}, {flags_name})' else: return f'KernRe({pattern})' def __add__(self, other): """ Allows adding two regular expressions into one. """ return KernRe(str(self) + str(other), cache=self.cache or other.cache, flags=self.regex.flags | other.regex.flags) def match(self, string): """ Handles a re.match storing its results. """ self.last_match = self.regex.match(string) return self.last_match def search(self, string): """ Handles a re.search storing its results. """ self.last_match = self.regex.search(string) return self.last_match def finditer(self, string): """ Alias to re.finditer. """ return self.regex.finditer(string) def findall(self, string): """ Alias to re.findall. """ return self.regex.findall(string) def split(self, string): """ Alias to re.split. """ return self.regex.split(string) def sub(self, sub, string, count=0): """ Alias to re.sub. """ return self.regex.sub(sub, string, count=count) def group(self, num): """ Returns the group results of the last match. """ return self.last_match.group(num) def groups(self): """ Returns the group results of the last match """ return self.last_match.groups()
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>.
"""
Regular expression ancillary classes.
Those help caching regular expressions and do matching for kernel-doc.
"""
import re
# Local cache for regular expressions
re_cache = {}
class KernRe:
"""
Helper class to simplify regex declaration and usage.
It calls re.compile for a given pattern. It also allows adding
regular expressions and define sub at class init time.
Regular expressions can be cached via an argument, helping to speedup
searches.
"""
def _add_regex(self, string, flags):
"""
Adds a new regex or reuses it from the cache.
"""
self.regex = re_cache.get(string, None)
if not self.regex:
self.regex = re.compile(string, flags=flags)
if self.cache:
re_cache[string] = self.regex
def __init__(self, string, cache=True, flags=0):
"""
Compile a regular expression and initialize internal vars.
"""
self.cache = cache
self.last_match = None
self._add_regex(string, flags)
def __str__(self):
"""
Return the regular expression pattern.
"""
return self.regex.pattern
def __repr__(self):
"""
Returns a displayable version of the class init.
"""
flag_map = {
re.IGNORECASE: "re.I",
re.MULTILINE: "re.M",
re.DOTALL: "re.S",
re.VERBOSE: "re.X",
}
flags = []
for flag, name in flag_map.items():
if self.regex.flags & flag:
flags.append(name)
flags_name = " | ".join(flags)
max_len = 60
pattern = ""
for pos in range(0, len(self.regex.pattern), max_len):
pattern += '"' + self.regex.pattern[pos:max_len + pos] + '" '
if flags_name:
return f'KernRe({pattern}, {flags_name})'
else:
return f'KernRe({pattern})'
def __add__(self, other):
"""
Allows adding two regular expressions into one.
"""
return KernRe(str(self) + str(other), cache=self.cache or other.cache,
flags=self.regex.flags | other.regex.flags)
def match(self, string):
"""
Handles a re.match storing its results.
"""
self.last_match = self.regex.match(string)
return self.last_match
def search(self, string):
"""
Handles a re.search storing its results.
"""
self.last_match = self.regex.search(string)
return self.last_match
def finditer(self, string):
"""
Alias to re.finditer.
"""
return self.regex.finditer(string)
def findall(self, string):
"""
Alias to re.findall.
"""
return self.regex.findall(string)
def split(self, string):
"""
Alias to re.split.
"""
return self.regex.split(string)
def sub(self, sub, string, count=0):
"""
Alias to re.sub.
"""
return self.regex.sub(sub, string, count=count)
def group(self, num):
"""
Returns the group results of the last match.
"""
return self.last_match.group(num)
def groups(self):
"""
Returns the group results of the last match
"""
return self.last_match.groups()