Match multiple (possibly overlapping) regular expressions in a single scan. A regex set corresponds to the union of two or more regular expressions. That is, a regex set will match text where at least one of its constituent regular expressions matches. A regex set as its formulated
| 235 | |
| 236 | |
| 237 | class RureSet(object): |
| 238 | """ Match multiple (possibly overlapping) regular expressions in a single |
| 239 | scan. |
| 240 | |
| 241 | A regex set corresponds to the union of two or more regular expressions. |
| 242 | That is, a regex set will match text where at least one of its constituent |
| 243 | regular expressions matches. A regex set as its formulated here provides a |
| 244 | touch more power: it will also report which regular expressions in the set |
| 245 | match. Indeed, this is the key difference between regex sets and a single |
| 246 | Regex with many alternates, since only one alternate can match at a time. |
| 247 | """ |
| 248 | def __init__(self, *res, **options): |
| 249 | |
| 250 | """ Compiles a regular expression. Once compiled, it can be used |
| 251 | repeatedly to search, split or replace text in a string. |
| 252 | |
| 253 | :param res: List of Bytestring expressions to compile |
| 254 | :param kwargs: Config options to pass (flags bitmask, |
| 255 | size_limit, |
| 256 | dfa_size_limit) |
| 257 | """ |
| 258 | |
| 259 | flags = options.pop('flags', DEFAULT_FLAGS) |
| 260 | if not all(isinstance(re, bytes) for re in res): |
| 261 | raise TypeError("'rure.lib.RureSet' must be instantiated with a " |
| 262 | "list of bytestrings as first argument.") |
| 263 | |
| 264 | self._err = _native.ffi.gc(_native.lib.rure_error_new(), _native.lib.rure_error_free) |
| 265 | self._opts = _native.ffi.gc(_native.lib.rure_options_new(), _native.lib.rure_options_free) |
| 266 | self.options = options |
| 267 | if 'size_limit' in options: |
| 268 | _native.lib.rure_options_size_limit(self._opts, options['size_limit']) |
| 269 | if 'dfa_size_limit' in options: |
| 270 | _native.lib.rure_options_dfa_size_limit(self._opts, |
| 271 | options['dfa_size_limit']) |
| 272 | |
| 273 | patterns = [] |
| 274 | patterns_lengths = [] |
| 275 | for re in res: |
| 276 | patterns.append(_native.ffi.new("uint8_t []", re)) |
| 277 | patterns_lengths.append(len(re)) |
| 278 | |
| 279 | s = checked_call( |
| 280 | _native.lib.rure_compile_set, |
| 281 | self._err, |
| 282 | _native.ffi.new("uint8_t *[]", patterns), |
| 283 | _native.ffi.new("size_t []", patterns_lengths), |
| 284 | len(patterns), |
| 285 | flags, |
| 286 | self._opts) |
| 287 | self._ptr = _native.ffi.gc(s, _native.lib.rure_set_free) |
| 288 | |
| 289 | def __len__(self): |
| 290 | return _native.lib.rure_set_len(self._ptr) |
| 291 | |
| 292 | @accepts_bytes |
| 293 | def is_match(self, haystack, start=0): |
| 294 | """ |
no outgoing calls