Module: XRay::SearchPattern

Defined in:
lib/aws-xray-sdk/search_pattern.rb

Overview

custom pattern matching for performance and the SDK use cases.

Class Method Summary collapse

Class Method Details

.simple_wildcard_match?(pattern:, text:) ⇒ Boolean



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/aws-xray-sdk/search_pattern.rb', line 61

def self.simple_wildcard_match?(pattern:, text:)
  j = 0
  pattern_len = pattern.length
  text_len = text.length
  (0...pattern_len).each do |i|
    p = pattern[i]
    # Presumption for this method is that globs only occur at end
    return true if p == '*'
    if p == '?'
      # No character to match
      return false if j == text_len
    else
      return false if j >= text_len || p != text[j]
    end
    j += 1
  end
  # Ate up all the pattern and didn't end at a glob, so a match
  # will have consumed all the text
  j == text_len
end

.wildcard_match?(pattern:, text:, case_insensitive: true) ⇒ Boolean

Performs a case-insensitive wildcard match against two strings. This method works with pseduo-regex chars; specifically ? and * are supported. An asterisk (*) represents any combination of characters. A question mark (?) represents any single character.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/aws-xray-sdk/search_pattern.rb', line 11

def self.wildcard_match?(pattern:, text:, case_insensitive: true)
  return false unless pattern && text
  pattern_len = pattern.length
  text_len = text.length
  return text_len.zero? if pattern_len.zero?
  # Check the special case of a single * pattern, as it's common
  return true if pattern == '*'

  if case_insensitive
    # do not mutate original input
    pattern = pattern.downcase
    text = text.downcase
  end
  # Infix globs are relatively rare, and the below search is expensive.
  # Check for infix globs and, in their absence, do the simple thing.
  if !pattern.include?('*') || pattern.index('*') == pattern_len - 1
    return simple_wildcard_match? pattern: pattern, text: text
  end

  # The res[i] is used to record if there is a match between
  # the first i chars in text and the first j chars in pattern.
  # So will return res[textLength+1] in the end
  # Loop from the beginning of the pattern
  # case not '*': if text[i]==pattern[j] or pattern[j] is '?',
  # and res[i] is true, set res[i+1] to true, otherwise false.
  # case '*': since '*' can match any globing, as long as there is a true
  # in res before i, all the res[i+1], res[i+2],...,res[textLength]
  # could be true
  res = Array.new(text_len + 1)
  res[0] = true
  (0...pattern_len).each do |j|
    p = pattern[j]
    if p != '*'
      (text_len - 1).downto(0) do |i|
        res[i + 1] = res[i] && (p == '?' || (p == text[i]))
      end
    else
      i = 0
      i += 1 while i <= text_len && !res[i]
      (i..text_len + 1).each do |m|
        res[m] = true
      end
    end
    res[0] = res[0] && (p == '*')
  end
  res[text_len]
end