#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 # Copyright(c) 2025: Mauro Carvalho Chehab . """ 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()