Skip to content

Commit

Permalink
matcher struct to tune wildcard chars
Browse files Browse the repository at this point in the history
  • Loading branch information
vodkaslime committed Sep 26, 2022
1 parent 87ec43d commit b32279b
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 10 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# wildcard

A simple golang wildcard matcher. Golang has pretty well built regex functionalities, but it does not have wildcard matcher that works as nicely. Therefore this package serves the need to check whether a string matches a pattern in the rule of wildcard.
25 changes: 19 additions & 6 deletions wildcard.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ package wildcard

import "strings"

func Match(pattern string, s string) (bool, error) {
type Matcher struct {
S byte
M byte
}

func NewMatcher() *Matcher {
return &Matcher{
S: '?',
M: '*',
}
}

func (m *Matcher) Match(pattern string, s string) (bool, error) {
// Edge cases.
if pattern == "*" {
if pattern == string(m.M) {
return true, nil
}

Expand All @@ -17,7 +29,8 @@ func Match(pattern string, s string) (bool, error) {

// If pattern does not contain wildcard chars, just compare the strings
// to avoid extra memory allocation.
if !strings.Contains(pattern, "*") && !strings.Contains(pattern, ".") {
if !strings.Contains(pattern, string(m.M)) &&
!strings.Contains(pattern, string(m.S)) {
return pattern == s, nil
}

Expand All @@ -32,7 +45,7 @@ func Match(pattern string, s string) (bool, error) {
dp[0][0] = true

for i := 0; i < lp; i++ {
if pattern[i] == '*' {
if pattern[i] == m.M {
dp[i+1][0] = dp[i][0]
} else {
dp[i+1][0] = false
Expand All @@ -49,9 +62,9 @@ func Match(pattern string, s string) (bool, error) {
pc := pattern[i]
sc := s[j]
switch pattern[i] {
case '*':
case m.M:
dp[i+1][j+1] = dp[i][j] || dp[i][j+1] || dp[i+1][j]
case '.':
case m.S:
dp[i+1][j+1] = dp[i][j]
default:
if pc == sc {
Expand Down
41 changes: 37 additions & 4 deletions wildcard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,36 @@ type testCase struct {

func TestMatch(t *testing.T) {

testCases := []testCase{
testCases1 := []testCase{
{"", "", true},
{"*", "", true},
{"?", "", false},
{"", "a", false},
{"abc", "abc", true},
{"abc", "ac", false},
{"abc", "abd", false},
{"a?c", "abc", true},
{"a*c", "abc", true},
{"a*c", "abcbc", true},
{"a*c", "abcbd", false},
{"a*b??c", "ajcbjcklbjic", true},
{"a*b??c", "ajcbjcklbjimc", false},
{"a*b*c", "ajkembbcldkcedc", true},
}

m1 := NewMatcher()
for _, tc := range testCases1 {
m, err := m1.Match(tc.p, tc.s)
if !assert.Equal(t, m, tc.m) {
println(tc.p, tc.s, tc.m)
}
assert.Nil(t, err)
}

m2 := NewMatcher()
m2.S = '.'

testCases2 := []testCase{
{"", "", true},
{"*", "", true},
{".", "", false},
Expand All @@ -23,17 +52,21 @@ func TestMatch(t *testing.T) {
{"abc", "ac", false},
{"abc", "abd", false},
{"a.c", "abc", true},
{"a?c", "abc", false},
{"a*c", "abc", true},
{"a*c", "abcbc", true},
{"a*c", "abcbd", false},
{"a*b..c", "ajcbjcklbjic", true},
{"a*b.?c", "ajcbjcklbjic", false},
{"a*b..c", "ajcbjcklbjimc", false},
{"a*b*c", "ajkembbcldkcedc", true},
}

for _, tc := range testCases {
m, err := Match(tc.p, tc.s)
assert.Equal(t, m, tc.m)
for _, tc := range testCases2 {
m, err := m2.Match(tc.p, tc.s)
if !assert.Equal(t, m, tc.m) {
println(tc.p, tc.s, tc.m)
}
assert.Nil(t, err)
}
}

0 comments on commit b32279b

Please sign in to comment.