Files
pekoe/internal/glob/glob.go
eleksir 92cd652b0d Add stub database selection, and fix differences between pekoe and c-redis
- PUBSUB CHANNELS glob pattern matching
- Implement SELECT + max DB validation (0-15) (default db max is 16), for perl clients
- CLIENT KILL ID (single/range) + MAXAGE
- CLIENT INFO events + resp fields
- PUBSUB SHARDCHANNELS/SHARDNUMSUB stubs
2026-04-03 01:02:13 +03:00

59 lines
1.4 KiB
Go

// @tag glob
package glob
// Match checks if a string matches a glob-style pattern.
// Supports:
// - * (asterisk): matches any sequence of characters (including empty)
// - ? (question): matches any single character
//
// This matches Redis PUBSUB CHANNELS pattern behavior.
func Match(pattern, s string) bool {
if pattern == "" {
return s == ""
}
if pattern == "*" {
return true
}
// Simple glob matching using dynamic programming
// Convert pattern to regex-like matching
patternLen := len(pattern)
sLen := len(s)
// dp[i][j] = true if pattern[0:i] matches s[0:j]
dp := make([][]bool, patternLen+1)
for i := range dp {
dp[i] = make([]bool, sLen+1)
}
// Empty pattern matches empty string
dp[0][0] = true
// Handle leading * in pattern
for i := 1; i <= patternLen; i++ {
if pattern[i-1] == '*' {
dp[i][0] = dp[i-1][0]
}
}
// Fill the DP table
for i := 1; i <= patternLen; i++ {
for j := 1; j <= sLen; j++ {
switch pattern[i-1] {
case '*':
// * matches: either consume nothing (stay at same position in pattern)
// or consume one character from string
dp[i][j] = dp[i-1][j] || dp[i][j-1]
case '?':
// ? matches any single character
dp[i][j] = dp[i-1][j-1]
default:
// Literal character must match exactly
dp[i][j] = dp[i-1][j-1] && pattern[i-1] == s[j-1]
}
}
}
return dp[patternLen][sLen]
}