1package match
2
3import (
4	"fmt"
5)
6
7type EveryOf struct {
8	Matchers Matchers
9}
10
11func NewEveryOf(m ...Matcher) EveryOf {
12	return EveryOf{Matchers(m)}
13}
14
15func (self *EveryOf) Add(m Matcher) error {
16	self.Matchers = append(self.Matchers, m)
17	return nil
18}
19
20func (self EveryOf) Len() (l int) {
21	for _, m := range self.Matchers {
22		if ml := m.Len(); l > 0 {
23			l += ml
24		} else {
25			return -1
26		}
27	}
28
29	return
30}
31
32func (self EveryOf) Index(s string) (int, []int) {
33	var index int
34	var offset int
35
36	// make `in` with cap as len(s),
37	// cause it is the maximum size of output segments values
38	next := acquireSegments(len(s))
39	current := acquireSegments(len(s))
40
41	sub := s
42	for i, m := range self.Matchers {
43		idx, seg := m.Index(sub)
44		if idx == -1 {
45			releaseSegments(next)
46			releaseSegments(current)
47			return -1, nil
48		}
49
50		if i == 0 {
51			// we use copy here instead of `current = seg`
52			// cause seg is a slice from reusable buffer `in`
53			// and it could be overwritten in next iteration
54			current = append(current, seg...)
55		} else {
56			// clear the next
57			next = next[:0]
58
59			delta := index - (idx + offset)
60			for _, ex := range current {
61				for _, n := range seg {
62					if ex+delta == n {
63						next = append(next, n)
64					}
65				}
66			}
67
68			if len(next) == 0 {
69				releaseSegments(next)
70				releaseSegments(current)
71				return -1, nil
72			}
73
74			current = append(current[:0], next...)
75		}
76
77		index = idx + offset
78		sub = s[index:]
79		offset += idx
80	}
81
82	releaseSegments(next)
83
84	return index, current
85}
86
87func (self EveryOf) Match(s string) bool {
88	for _, m := range self.Matchers {
89		if !m.Match(s) {
90			return false
91		}
92	}
93
94	return true
95}
96
97func (self EveryOf) String() string {
98	return fmt.Sprintf("<every_of:[%s]>", self.Matchers)
99}
100