Module: Ruby::Rego::Builtins::Regex::GlobIntersection
- Defined in:
- lib/ruby/rego/builtins/regex/glob_intersection.rb,
lib/ruby/rego/builtins/regex/glob_intersection/trim.rb,
lib/ruby/rego/builtins/regex/glob_intersection/tokenizer.rb,
lib/ruby/rego/builtins/regex/glob_intersection/intersector.rb
Overview
Reopens GlobIntersection to host the recursive intersection engine. Lives apart from the tokenizer/trim core so the main file stays under RubyCritic’s complexity budget. GlobError, MAX_WORK, and match? live in the main file (loaded first, before this require_relative).
Defined Under Namespace
Classes: GlobError, Intersector, RuneBudget, Token
Constant Summary collapse
- MAX_GLOB_SOURCE =
Maximum byte length of a single glob pattern.
100_000- MAX_GLOB_FLAGS =
Maximum number of flags (
*/+) in the smaller-flagged glob; the algorithm is exponential in this count. 20- MAX_SET_RUNES =
Maximum codepoints all character-class ranges in one glob may expand to, cumulatively. Bounds tokenization work, which runs before MAX_WORK applies.
1_000_000- MAX_WORK =
Maximum number of intersection steps before bailing out.
5_000_000
Class Method Summary collapse
-
.match?(token_lhs, token_rhs) ⇒ Boolean
Whether two atoms (ignoring flags) can match a common character.
-
.new_glob(input) ⇒ Array<Token>
-
.non_empty?(lhs, rhs) ⇒ bool
-
.tokenize(input) ⇒ Object
Class Method Details
.match?(token_lhs, token_rhs) ⇒ Boolean
Whether two atoms (ignoring flags) can match a common character.
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/ruby/rego/builtins/regex/glob_intersection.rb', line 140 def self.match?(token_lhs, token_rhs) type_lhs = token_lhs.type type_rhs = token_rhs.type return true if type_lhs == :dot || type_rhs == :dot return token_lhs.rune == token_rhs.rune if type_lhs == :char && type_rhs == :char # Only :char and :set remain; a char's codepoint vs the other's rune set. return runes_of(token_rhs).include?(token_lhs.rune.to_s.ord) if type_lhs == :char return runes_of(token_lhs).include?(token_rhs.rune.to_s.ord) if type_rhs == :char runes_of(token_lhs).intersect?(runes_of(token_rhs)) end |
.new_glob(input) ⇒ Array<Token>
109 110 111 112 113 |
# File 'lib/ruby/rego/builtins/regex/glob_intersection.rb', line 109 def self.new_glob(input) raise GlobError, "glob too long" if input.bytesize > MAX_GLOB_SOURCE simplify(tokenize(input)) end |
.non_empty?(lhs, rhs) ⇒ bool
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ruby/rego/builtins/regex/glob_intersection.rb', line 95 def self.non_empty?(lhs, rhs) lhs = new_glob(lhs) rhs = new_glob(rhs) # Checked before trimming (as gintersect does); trimming only removes # unflagged tokens, so the post-trim flag count is never higher. ensure_within_flag_limit(lhs, rhs) lhs, rhs, prefix_ok = trim_globs(lhs, rhs) return false unless prefix_ok Intersector.new.intersect_normal(lhs, rhs) end |
.tokenize(input) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/ruby/rego/builtins/regex/glob_intersection/tokenizer.rb', line 27 def self.tokenize(input) chars = input.chars tokens = [] # @type var tokens: Array[Token] budget = RuneBudget.new(MAX_SET_RUNES) index = 0 while index < chars.length token, index = next_token(chars, index, budget) tokens << token end tokens end |