File: wildcard.go

package info (click to toggle)
singularity-container 4.1.5%2Bds4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 43,876 kB
  • sloc: asm: 14,840; sh: 3,190; ansic: 1,751; awk: 414; makefile: 413; python: 99
file content (87 lines) | stat: -rw-r--r-- 2,019 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package wildcard

import (
	"regexp"
	"strings"

	"github.com/pkg/errors"
)

// New returns a wildcard object for a string that contains "*" symbols.
func New(s string) (*Wildcard, error) {
	reStr, err := Wildcard2Regexp(s)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to translate wildcard %q to regexp", s)
	}
	re, err := regexp.Compile(reStr)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to compile regexp %q (translated from wildcard %q)", reStr, s)
	}
	w := &Wildcard{
		orig: s,
		re:   re,
	}
	return w, nil
}

// Wildcard2Regexp translates a wildcard string to a regexp string.
func Wildcard2Regexp(wildcard string) (string, error) {
	s := regexp.QuoteMeta(wildcard)
	if strings.Contains(s, "\\*\\*") {
		return "", errors.New("invalid wildcard: \"**\"")
	}
	s = strings.ReplaceAll(s, "\\*", "(.*)")
	s = "^" + s + "$"
	return s, nil
}

// Wildcard is a wildcard matcher object.
type Wildcard struct {
	orig string
	re   *regexp.Regexp
}

// String implements fmt.Stringer.
func (w *Wildcard) String() string {
	return w.orig
}

// Match returns a non-nil Match on match.
func (w *Wildcard) Match(q string) *Match {
	submatches := w.re.FindStringSubmatch(q)
	if len(submatches) == 0 {
		return nil
	}
	m := &Match{
		w:          w,
		Submatches: submatches,
		// FIXME: avoid executing regexp twice
		idx: w.re.FindStringSubmatchIndex(q),
	}
	return m
}

// Match is a matched result.
type Match struct {
	w          *Wildcard
	Submatches []string // 0: the entire query, 1: the first submatch, 2: the second submatch, ...
	idx        []int
}

// String implements fmt.Stringer.
func (m *Match) String() string {
	if len(m.Submatches) == 0 {
		return ""
	}
	return m.Submatches[0]
}

// Format formats submatch strings like "$1", "$2".
func (m *Match) Format(f string) (string, error) {
	if m.w == nil || len(m.Submatches) == 0 || len(m.idx) == 0 {
		return "", errors.New("invalid state")
	}
	var b []byte
	b = m.w.re.ExpandString(b, f, m.Submatches[0], m.idx)
	return string(b), nil
}