diff --git a/compiler.go b/compiler.go index fa9ab91..c0d087b 100644 --- a/compiler.go +++ b/compiler.go @@ -14,7 +14,7 @@ func optimize(matcher match.Matcher) match.Matcher { case match.Any: if len(m.Separators) == 0 { - return match.Super{} + return match.NewSuper() } case match.AnyOf: @@ -54,23 +54,23 @@ func optimize(matcher match.Matcher) match.Matcher { rs, rightSuffix := m.Right.(match.Suffix) if leftSuper && rightSuper { - return match.Contains{r.Str, false} + return match.NewContains(r.Str, false) } if leftSuper && rightNil { - return match.Suffix{r.Str} + return match.NewSuffix(r.Str) } if rightSuper && leftNil { - return match.Prefix{r.Str} + return match.NewPrefix(r.Str) } if leftNil && rightSuffix { - return match.PrefixSuffix{Prefix: r.Str, Suffix: rs.Suffix} + return match.NewPrefixSuffix(r.Str, rs.Suffix) } if rightNil && leftPrefix { - return match.PrefixSuffix{Prefix: lp.Prefix, Suffix: r.Str} + return match.NewPrefixSuffix(lp.Prefix, r.Str) } return m @@ -124,7 +124,7 @@ func glueAsRow(matchers []match.Matcher) match.Matcher { } } - return match.NewRow(c, l) + return match.NewRow(l, c...) } func glueAsEvery(matchers []match.Matcher) match.Matcher { @@ -182,29 +182,29 @@ func glueAsEvery(matchers []match.Matcher) match.Matcher { } if hasSuper && !hasAny && !hasSingle { - return match.Super{} + return match.NewSuper() } if hasAny && !hasSuper && !hasSingle { - return match.Any{separator} + return match.NewAny(separator) } if (hasAny || hasSuper) && min > 0 && len(separator) == 0 { - return match.Min{min} + return match.NewMin(min) } - every := match.EveryOf{} + every := match.NewEveryOf() if min > 0 { - every.Add(match.Min{min}) + every.Add(match.NewMin(min)) if !hasAny && !hasSuper { - every.Add(match.Max{min}) + every.Add(match.NewMax(min)) } } if len(separator) > 0 { - every.Add(match.Contains{string(separator), true}) + every.Add(match.NewContains(string(separator), true)) } return every @@ -474,7 +474,7 @@ func doAnyOf(n *nodeAnyOf, s []rune) (match.Matcher, error) { var matchers []match.Matcher for _, desc := range n.children() { if desc == nil { - matchers = append(matchers, match.Nothing{}) + matchers = append(matchers, match.NewNothing()) continue } @@ -485,7 +485,7 @@ func doAnyOf(n *nodeAnyOf, s []rune) (match.Matcher, error) { matchers = append(matchers, optimize(m)) } - return match.AnyOf{matchers}, nil + return match.NewAnyOf(matchers...), nil } func do(leaf node, s []rune) (m match.Matcher, err error) { @@ -500,7 +500,7 @@ func do(leaf node, s []rune) (m match.Matcher, err error) { var matchers []match.Matcher for _, desc := range n.children() { if desc == nil { - matchers = append(matchers, match.Nothing{}) + matchers = append(matchers, match.NewNothing()) continue } @@ -511,12 +511,12 @@ func do(leaf node, s []rune) (m match.Matcher, err error) { matchers = append(matchers, optimize(m)) } - return match.AnyOf{matchers}, nil + return match.NewAnyOf(matchers...), nil case *nodePattern: nodes := leaf.children() if len(nodes) == 0 { - return match.Nothing{}, nil + return match.NewNothing(), nil } var matchers []match.Matcher @@ -534,19 +534,19 @@ func do(leaf node, s []rune) (m match.Matcher, err error) { } case *nodeList: - m = match.List{[]rune(n.chars), n.not} + m = match.NewList([]rune(n.chars), n.not) case *nodeRange: - m = match.Range{n.lo, n.hi, n.not} + m = match.NewRange(n.lo, n.hi, n.not) case *nodeAny: - m = match.Any{s} + m = match.NewAny(s) case *nodeSuper: - m = match.Super{} + m = match.NewSuper() case *nodeSingle: - m = match.Single{s} + m = match.NewSingle(s) case *nodeText: m = match.NewText(n.text) @@ -633,19 +633,19 @@ func do2(node node, s []rune) ([]match.Matcher, error) { } case *nodeList: - result = append(result, match.List{[]rune(n.chars), n.not}) + result = append(result, match.NewList([]rune(n.chars), n.not)) case *nodeRange: - result = append(result, match.Range{n.lo, n.hi, n.not}) + result = append(result, match.NewRange(n.lo, n.hi, n.not)) case *nodeAny: - result = append(result, match.Any{s}) + result = append(result, match.NewAny(s)) case *nodeSuper: - result = append(result, match.Super{}) + result = append(result, match.NewSuper()) case *nodeSingle: - result = append(result, match.Single{s}) + result = append(result, match.NewSingle(s)) case *nodeText: result = append(result, match.NewText(n.text)) @@ -669,7 +669,7 @@ func compile(ast *nodePattern, s []rune) (Glob, error) { // if len(ms) == 1 { // return ms[0], nil // } else { - // return match.AnyOf{ms}, nil + // return match.NewAnyOf(ms), nil // } g, err := do(ast, s) diff --git a/compiler_test.go b/compiler_test.go index 0be7b76..f2d0c70 100644 --- a/compiler_test.go +++ b/compiler_test.go @@ -15,40 +15,40 @@ func TestGlueMatchers(t *testing.T) { }{ { []match.Matcher{ - match.Super{}, - match.Single{}, + match.NewSuper(), + match.NewSingle(nil), }, - match.Min{1}, + match.NewMin(1), }, { []match.Matcher{ - match.Any{separators}, - match.Single{separators}, + match.NewAny(separators), + match.NewSingle(separators), }, match.EveryOf{match.Matchers{ - match.Min{1}, - match.Contains{string(separators), true}, + match.NewMin(1), + match.NewContains(string(separators), true), }}, }, { []match.Matcher{ - match.Single{}, - match.Single{}, - match.Single{}, + match.NewSingle(nil), + match.NewSingle(nil), + match.NewSingle(nil), }, match.EveryOf{match.Matchers{ - match.Min{3}, - match.Max{3}, + match.NewMin(3), + match.NewMax(3), }}, }, { []match.Matcher{ - match.List{[]rune{'a'}, true}, - match.Any{[]rune{'a'}}, + match.NewList([]rune{'a'}, true), + match.NewAny([]rune{'a'}), }, match.EveryOf{match.Matchers{ - match.Min{1}, - match.Contains{"a", true}, + match.NewMin(1), + match.NewContains("a", true), }}, }, } { @@ -59,7 +59,7 @@ func TestGlueMatchers(t *testing.T) { } if !reflect.DeepEqual(act, test.exp) { - t.Errorf("#%d unexpected convert matchers result:\nact: %s;\nexp: %s", id, act, test.exp) + t.Errorf("#%d unexpected convert matchers result:\nact: %#v;\nexp: %#v", id, act, test.exp) continue } } @@ -72,15 +72,15 @@ func TestCompileMatchers(t *testing.T) { }{ { []match.Matcher{ - match.Super{}, - match.Single{separators}, + match.NewSuper(), + match.NewSingle(separators), match.NewText("c"), }, match.NewBTree( match.NewText("c"), match.NewBTree( - match.Single{separators}, - match.Super{}, + match.NewSingle(separators), + match.NewSuper(), nil, ), nil, @@ -88,32 +88,32 @@ func TestCompileMatchers(t *testing.T) { }, { []match.Matcher{ - match.Any{}, + match.NewAny(nil), match.NewText("c"), - match.Any{}, + match.NewAny(nil), }, match.NewBTree( match.NewText("c"), - match.Any{}, - match.Any{}, + match.NewAny(nil), + match.NewAny(nil), ), }, { []match.Matcher{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - match.Single{}, + match.NewSingle(nil), }, - match.Row{ - Matchers: match.Matchers{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRow( + 4, + match.Matchers{ + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - match.Single{}, - }, - RunesLength: 4, - }, + match.NewSingle(nil), + }..., + ), }, } { act, err := compileMatchers(test.in) @@ -123,7 +123,7 @@ func TestCompileMatchers(t *testing.T) { } if !reflect.DeepEqual(act, test.exp) { - t.Errorf("#%d unexpected convert matchers result:\nact: %s;\nexp: %s", id, act, test.exp) + t.Errorf("#%d unexpected convert matchers result:\nact: %#v\nexp: %#v", id, act, test.exp) continue } } @@ -135,52 +135,52 @@ func TestConvertMatchers(t *testing.T) { }{ { []match.Matcher{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - match.Single{}, - match.Any{}, + match.NewSingle(nil), + match.NewAny(nil), }, []match.Matcher{ - match.Row{ - Matchers: match.Matchers{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRow( + 4, + []match.Matcher{ + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - match.Single{}, - }, - RunesLength: 4, - }, - match.Any{}, + match.NewSingle(nil), + }..., + ), + match.NewAny(nil), }, }, { []match.Matcher{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - match.Single{}, - match.Any{}, - match.Single{}, - match.Single{}, - match.Any{}, + match.NewSingle(nil), + match.NewAny(nil), + match.NewSingle(nil), + match.NewSingle(nil), + match.NewAny(nil), }, []match.Matcher{ - match.Row{ - Matchers: match.Matchers{ - match.Range{'a', 'c', true}, - match.List{[]rune{'z', 't', 'e'}, false}, + match.NewRow( + 3, + match.Matchers{ + match.NewRange('a', 'c', true), + match.NewList([]rune{'z', 't', 'e'}, false), match.NewText("c"), - }, - RunesLength: 3, - }, - match.Min{3}, + }..., + ), + match.NewMin(3), }, }, } { act := minimizeMatchers(test.in) if !reflect.DeepEqual(act, test.exp) { - t.Errorf("#%d unexpected convert matchers 2 result:\nact: %s;\nexp: %s", id, act, test.exp) + t.Errorf("#%d unexpected convert matchers 2 result:\nact: %#v\nexp: %#v", id, act, test.exp) continue } } @@ -213,20 +213,20 @@ func TestCompiler(t *testing.T) { { ast: pattern(&nodeAny{}), sep: separators, - result: match.Any{separators}, + result: match.NewAny(separators), }, { ast: pattern(&nodeAny{}), - result: match.Super{}, + result: match.NewSuper(), }, { ast: pattern(&nodeSuper{}), - result: match.Super{}, + result: match.NewSuper(), }, { ast: pattern(&nodeSingle{}), sep: separators, - result: match.Single{separators}, + result: match.NewSingle(separators), }, { ast: pattern(&nodeRange{ @@ -234,39 +234,39 @@ func TestCompiler(t *testing.T) { hi: 'z', not: true, }), - result: match.Range{'a', 'z', true}, + result: match.NewRange('a', 'z', true), }, { ast: pattern(&nodeList{ chars: "abc", not: true, }), - result: match.List{[]rune{'a', 'b', 'c'}, true}, + result: match.NewList([]rune{'a', 'b', 'c'}, true), }, { ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}), sep: separators, result: match.EveryOf{Matchers: match.Matchers{ - match.Min{3}, - match.Contains{string(separators), true}, + match.NewMin(3), + match.NewContains(string(separators), true), }}, }, { ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}), - result: match.Min{3}, + result: match.NewMin(3), }, { ast: pattern(&nodeAny{}, &nodeText{text: "abc"}, &nodeSingle{}), sep: separators, result: match.NewBTree( - match.Row{ - Matchers: match.Matchers{ + match.NewRow( + 4, + match.Matchers{ match.NewText("abc"), - match.Single{separators}, - }, - RunesLength: 4, - }, - match.Any{separators}, + match.NewSingle(separators), + }..., + ), + match.NewAny(separators), nil, ), }, @@ -274,49 +274,49 @@ func TestCompiler(t *testing.T) { ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSingle{}), sep: separators, result: match.NewBTree( - match.Row{ - Matchers: match.Matchers{ - match.Single{separators}, + match.NewRow( + 5, + match.Matchers{ + match.NewSingle(separators), match.NewText("abc"), - match.Single{separators}, - }, - RunesLength: 5, - }, - match.Super{}, + match.NewSingle(separators), + }..., + ), + match.NewSuper(), nil, ), }, { ast: pattern(&nodeAny{}, &nodeText{text: "abc"}), - result: match.Suffix{"abc"}, + result: match.NewSuffix("abc"), }, { ast: pattern(&nodeText{text: "abc"}, &nodeAny{}), - result: match.Prefix{"abc"}, + result: match.NewPrefix("abc"), }, { ast: pattern(&nodeText{text: "abc"}, &nodeAny{}, &nodeText{text: "def"}), - result: match.PrefixSuffix{"abc", "def"}, + result: match.NewPrefixSuffix("abc", "def"), }, { ast: pattern(&nodeAny{}, &nodeAny{}, &nodeAny{}, &nodeText{text: "abc"}, &nodeAny{}, &nodeAny{}), - result: match.Contains{"abc", false}, + result: match.NewContains("abc", false), }, { ast: pattern(&nodeAny{}, &nodeAny{}, &nodeAny{}, &nodeText{text: "abc"}, &nodeAny{}, &nodeAny{}), sep: separators, result: match.NewBTree( match.NewText("abc"), - match.Any{separators}, - match.Any{separators}, + match.NewAny(separators), + match.NewAny(separators), ), }, { ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSuper{}, &nodeSingle{}), result: match.NewBTree( match.NewText("abc"), - match.Min{1}, - match.Min{1}, + match.NewMin(1), + match.NewMin(1), ), }, { @@ -348,9 +348,9 @@ func TestCompiler(t *testing.T) { match.NewText("abc"), nil, match.AnyOf{Matchers: match.Matchers{ - match.Single{}, - match.List{List: []rune{'d', 'e', 'f'}}, - match.Nothing{}, + match.NewSingle(nil), + match.NewList([]rune{'d', 'e', 'f'}, false), + match.NewNothing(), }}, ), }, @@ -361,15 +361,15 @@ func TestCompiler(t *testing.T) { &nodeAny{}, ), result: match.NewBTree( - match.Row{ - Matchers: match.Matchers{ - match.Range{Lo: 'a', Hi: 'z'}, - match.Range{Lo: 'a', Hi: 'x', Not: true}, - }, - RunesLength: 2, - }, + match.NewRow( + 2, + match.Matchers{ + match.NewRange('a', 'z', false), + match.NewRange('a', 'x', true), + }..., + ), nil, - match.Super{}, + match.NewSuper(), ), }, { @@ -385,17 +385,17 @@ func TestCompiler(t *testing.T) { &nodeText{text: "ghi"}, ), )), - result: match.Row{ - RunesLength: 7, - Matchers: match.Matchers{ + result: match.NewRow( + 7, + match.Matchers{ match.NewText("abc"), match.AnyOf{Matchers: match.Matchers{ - match.List{List: []rune{'a', 'b', 'c'}}, - match.List{List: []rune{'d', 'e', 'f'}}, + match.NewList([]rune{'a', 'b', 'c'}, false), + match.NewList([]rune{'d', 'e', 'f'}, false), }}, match.NewText("ghi"), - }, - }, + }..., + ), }, // { // ast: pattern( @@ -403,21 +403,21 @@ func TestCompiler(t *testing.T) { // anyOf(&nodeText{text: "c"}, &nodeText{text: "d"}), // ), // result: match.AnyOf{Matchers: match.Matchers{ - // match.Row{Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"c", 1}}}, - // match.Row{Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"d"}}}, - // match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"c", 1}}}, - // match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"d"}}}, + // match.NewRow(Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"c", 1}}), + // match.NewRow(Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"d"}}), + // match.NewRow(Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"c", 1}}), + // match.NewRow(Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"d"}}), // }}, // }, } { - prog, err := compile(test.ast, test.sep) + m, err := compile(test.ast, test.sep) if err != nil { t.Errorf("compilation error: %s", err) continue } - if !reflect.DeepEqual(prog, test.result) { - t.Errorf("#%d results are not equal:\nexp: %s,\nact: %s", id, test.result, prog) + if !reflect.DeepEqual(m, test.result) { + t.Errorf("#%d results are not equal:\nexp: %#v\nact: %#v", id, test.result, m) continue } } @@ -426,105 +426,105 @@ func TestCompiler(t *testing.T) { const complexityString = "abcd" //func BenchmarkComplexityAny(b *testing.B) { -// m := match.Any{} +// m := match.NewAny(nil) // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityContains(b *testing.B) { -// m := match.Contains{} +// m := match.NewContains() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityList(b *testing.B) { -// m := match.List{} +// m := match.NewList() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityMax(b *testing.B) { -// m := match.Max{} +// m := match.NewMax() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityMin(b *testing.B) { -// m := match.Min{} +// m := match.NewMin() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityNothing(b *testing.B) { -// m := match.Nothing{} +// m := match.NewNothing() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityPrefix(b *testing.B) { -// m := match.Prefix{} +// m := match.NewPrefix() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityPrefixSuffix(b *testing.B) { -// m := match.PrefixSuffix{} +// m := match.NewPrefixSuffix() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityRange(b *testing.B) { -// m := match.Range{} +// m := match.NewRange() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityRow(b *testing.B) { -// m := match.Row{} +// m := match.NewRow() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexitySingle(b *testing.B) { -// m := match.Single{} +// m := match.NewSingle(nil) // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexitySuffix(b *testing.B) { -// m := match.Suffix{} +// m := match.NewSuffix() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexitySuper(b *testing.B) { -// m := match.Super{} +// m := match.NewSuper() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityText(b *testing.B) { -// m := match.Text{} +// m := match.NewText() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) // } //} //func BenchmarkComplexityAnyOf(b *testing.B) { -// m := match.AnyOf{} +// m := match.NewAnyOf() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) @@ -538,7 +538,7 @@ const complexityString = "abcd" // } //} //func BenchmarkComplexityEveryOf(b *testing.B) { -// m := match.EveryOf{} +// m := match.NewEveryOf() // for i := 0; i < b.N; i++ { // _ = m.Match(complexityString) // _, _ = m.Index(complexityString) diff --git a/match/any.go b/match/any.go index e7a2953..1d2d12b 100644 --- a/match/any.go +++ b/match/any.go @@ -9,6 +9,10 @@ type Any struct { Separators []rune } +func NewAny(s []rune) Any { + return Any{s} +} + func (self Any) Match(s string) bool { return strings.IndexAnyRunes(s, self.Separators) == -1 } diff --git a/match/any_of.go b/match/any_of.go index 8cdfed1..ffae2f6 100644 --- a/match/any_of.go +++ b/match/any_of.go @@ -8,6 +8,10 @@ type AnyOf struct { Matchers Matchers } +func NewAnyOf(m ...Matcher) AnyOf { + return AnyOf{Matchers(m)} +} + func (self *AnyOf) Add(m Matcher) error { self.Matchers = append(self.Matchers, m) return nil @@ -27,7 +31,6 @@ func (self AnyOf) Index(s string) (int, []int) { index := -1 segments := acquireSegments(len(s)) - for _, m := range self.Matchers { idx, seg := m.Index(s) if idx == -1 { diff --git a/match/any_of_test.go b/match/any_of_test.go index 44782e9..3b478cf 100644 --- a/match/any_of_test.go +++ b/match/any_of_test.go @@ -14,7 +14,7 @@ func TestAnyOfIndex(t *testing.T) { }{ { Matchers{ - Any{}, + NewAny(nil), NewText("b"), NewText("c"), }, @@ -24,8 +24,8 @@ func TestAnyOfIndex(t *testing.T) { }, { Matchers{ - Prefix{"b"}, - Suffix{"c"}, + NewPrefix("b"), + NewSuffix("c"), }, "abc", 0, @@ -41,7 +41,7 @@ func TestAnyOfIndex(t *testing.T) { []int{1}, }, } { - everyOf := AnyOf{test.matchers} + everyOf := NewAnyOf(test.matchers...) index, segments := everyOf.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) diff --git a/match/any_test.go b/match/any_test.go index e15a0c7..358f553 100644 --- a/match/any_test.go +++ b/match/any_test.go @@ -25,7 +25,7 @@ func TestAnyIndex(t *testing.T) { []int{0, 1, 2, 3}, }, } { - p := Any{test.sep} + p := NewAny(test.sep) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,7 +37,7 @@ func TestAnyIndex(t *testing.T) { } func BenchmarkIndexAny(b *testing.B) { - m := Any{bench_separators} + m := NewAny(bench_separators) for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -46,7 +46,7 @@ func BenchmarkIndexAny(b *testing.B) { } func BenchmarkIndexAnyParallel(b *testing.B) { - m := Any{bench_separators} + m := NewAny(bench_separators) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/btree.go b/match/btree.go index 8827035..a8130e9 100644 --- a/match/btree.go +++ b/match/btree.go @@ -129,5 +129,18 @@ func (self BTree) Match(s string) bool { } func (self BTree) String() string { - return fmt.Sprintf("%s]>", self.Left, self.Value, self.Right) + const n string = "" + var l, r string + if self.Left == nil { + l = n + } else { + l = self.Left.String() + } + if self.Right == nil { + r = n + } else { + r = self.Right.String() + } + + return fmt.Sprintf("%s]>", l, self.Value, r) } diff --git a/match/btree_test.go b/match/btree_test.go index 3a96786..3bd9ea5 100644 --- a/match/btree_test.go +++ b/match/btree_test.go @@ -11,17 +11,17 @@ func TestBTree(t *testing.T) { exp bool }{ { - NewBTree(NewText("abc"), Super{}, Super{}), + NewBTree(NewText("abc"), NewSuper(), NewSuper()), "abc", true, }, { - NewBTree(NewText("a"), Single{}, Single{}), + NewBTree(NewText("a"), NewSingle(nil), NewSingle(nil)), "aaa", true, }, { - NewBTree(NewText("b"), Single{}, nil), + NewBTree(NewText("b"), NewSingle(nil), nil), "bbb", false, }, @@ -29,8 +29,8 @@ func TestBTree(t *testing.T) { NewBTree( NewText("c"), NewBTree( - Single{}, - Super{}, + NewSingle(nil), + NewSuper(), nil, ), nil, diff --git a/match/contains.go b/match/contains.go index be20492..b4f57fc 100644 --- a/match/contains.go +++ b/match/contains.go @@ -10,6 +10,10 @@ type Contains struct { Not bool } +func NewContains(needle string, not bool) Contains { + return Contains{needle, not} +} + func (self Contains) Match(s string) bool { return strings.Contains(s, self.Needle) != self.Not } diff --git a/match/contains_test.go b/match/contains_test.go index f840793..931322e 100644 --- a/match/contains_test.go +++ b/match/contains_test.go @@ -42,7 +42,7 @@ func TestContainsIndex(t *testing.T) { []int{0, 1, 2, 3}, }, } { - p := Contains{test.prefix, test.not} + p := NewContains(test.prefix, test.not) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -54,7 +54,7 @@ func TestContainsIndex(t *testing.T) { } func BenchmarkIndexContains(b *testing.B) { - m := Contains{string(bench_separators), true} + m := NewContains(string(bench_separators), true) for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -63,7 +63,7 @@ func BenchmarkIndexContains(b *testing.B) { } func BenchmarkIndexContainsParallel(b *testing.B) { - m := Contains{string(bench_separators), true} + m := NewContains(string(bench_separators), true) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/every_of.go b/match/every_of.go index 9220f78..7c968ee 100644 --- a/match/every_of.go +++ b/match/every_of.go @@ -8,6 +8,10 @@ type EveryOf struct { Matchers Matchers } +func NewEveryOf(m ...Matcher) EveryOf { + return EveryOf{Matchers(m)} +} + func (self *EveryOf) Add(m Matcher) error { self.Matchers = append(self.Matchers, m) return nil @@ -31,7 +35,6 @@ func (self EveryOf) Index(s string) (int, []int) { // make `in` with cap as len(s), // cause it is the maximum size of output segments values - //todo opti!!! next := acquireSegments(len(s)) current := acquireSegments(len(s)) @@ -39,6 +42,8 @@ func (self EveryOf) Index(s string) (int, []int) { for i, m := range self.Matchers { idx, seg := m.Index(sub) if idx == -1 { + releaseSegments(next) + releaseSegments(current) return -1, nil } @@ -61,6 +66,8 @@ func (self EveryOf) Index(s string) (int, []int) { } if len(next) == 0 { + releaseSegments(next) + releaseSegments(current) return -1, nil } @@ -72,6 +79,8 @@ func (self EveryOf) Index(s string) (int, []int) { offset += idx } + releaseSegments(next) + return index, current } diff --git a/match/every_of_test.go b/match/every_of_test.go index 3f70a78..eb83f86 100644 --- a/match/every_of_test.go +++ b/match/every_of_test.go @@ -14,7 +14,7 @@ func TestEveryOfIndex(t *testing.T) { }{ { Matchers{ - Any{}, + NewAny(nil), NewText("b"), NewText("c"), }, @@ -24,16 +24,16 @@ func TestEveryOfIndex(t *testing.T) { }, { Matchers{ - Any{}, - Prefix{"b"}, - Suffix{"c"}, + NewAny(nil), + NewPrefix("b"), + NewSuffix("c"), }, "abc", 1, []int{2}, }, } { - everyOf := EveryOf{test.matchers} + everyOf := NewEveryOf(test.matchers...) index, segments := everyOf.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) diff --git a/match/list.go b/match/list.go index 00f2d98..fe0841f 100644 --- a/match/list.go +++ b/match/list.go @@ -12,10 +12,7 @@ type List struct { } func NewList(list []rune, not bool) List { - return List{ - List: list, - Not: not, - } + return List{list, not} } func (self List) Match(s string) bool { @@ -48,5 +45,5 @@ func (self List) String() string { not = "!" } - return fmt.Sprintf("", not, self.List) + return fmt.Sprintf("", not, string(self.List)) } diff --git a/match/max.go b/match/max.go index 5405594..d72f69e 100644 --- a/match/max.go +++ b/match/max.go @@ -9,6 +9,10 @@ type Max struct { Limit int } +func NewMax(l int) Max { + return Max{l} +} + func (self Max) Match(s string) bool { var l int for range s { @@ -22,8 +26,7 @@ func (self Max) Match(s string) bool { } func (self Max) Index(s string) (int, []int) { - segments := make([]int, 0, self.Limit+1) - + segments := acquireSegments(self.Limit + 1) segments = append(segments, 0) var count int for i, r := range s { diff --git a/match/max_test.go b/match/max_test.go index 005e3f0..2367628 100644 --- a/match/max_test.go +++ b/match/max_test.go @@ -25,7 +25,7 @@ func TestMaxIndex(t *testing.T) { []int{0, 1, 2, 3}, }, } { - p := Max{test.limit} + p := NewMax(test.limit) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,19 +37,21 @@ func TestMaxIndex(t *testing.T) { } func BenchmarkIndexMax(b *testing.B) { - m := Max{10} + m := NewMax(10) for i := 0; i < b.N; i++ { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } } func BenchmarkIndexMaxParallel(b *testing.B) { - m := Max{10} + m := NewMax(10) b.RunParallel(func(pb *testing.PB) { for pb.Next() { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } }) } diff --git a/match/min.go b/match/min.go index 6942e29..db57ac8 100644 --- a/match/min.go +++ b/match/min.go @@ -9,6 +9,10 @@ type Min struct { Limit int } +func NewMin(l int) Min { + return Min{l} +} + func (self Min) Match(s string) bool { var l int for range s { @@ -24,7 +28,12 @@ func (self Min) Match(s string) bool { func (self Min) Index(s string) (int, []int) { var count int - segments := make([]int, 0, len(s)-self.Limit+1) + c := len(s) - self.Limit + 1 + if c <= 0 { + return -1, nil + } + + segments := acquireSegments(c) for i, r := range s { count++ if count >= self.Limit { diff --git a/match/min_test.go b/match/min_test.go index 2bea4ee..ab854ae 100644 --- a/match/min_test.go +++ b/match/min_test.go @@ -25,7 +25,7 @@ func TestMinIndex(t *testing.T) { []int{3, 4}, }, } { - p := Min{test.limit} + p := NewMin(test.limit) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,19 +37,21 @@ func TestMinIndex(t *testing.T) { } func BenchmarkIndexMin(b *testing.B) { - m := Min{10} + m := NewMin(10) for i := 0; i < b.N; i++ { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } } func BenchmarkIndexMinParallel(b *testing.B) { - m := Min{10} + m := NewMin(10) b.RunParallel(func(pb *testing.PB) { for pb.Next() { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } }) } diff --git a/match/nothing.go b/match/nothing.go index 664ade9..0d4ecd3 100644 --- a/match/nothing.go +++ b/match/nothing.go @@ -6,6 +6,10 @@ import ( type Nothing struct{} +func NewNothing() Nothing { + return Nothing{} +} + func (self Nothing) Match(s string) bool { return len(s) == 0 } diff --git a/match/nothing_test.go b/match/nothing_test.go index 569969c..941c22d 100644 --- a/match/nothing_test.go +++ b/match/nothing_test.go @@ -22,7 +22,7 @@ func TestNothingIndex(t *testing.T) { []int{0}, }, } { - p := Nothing{} + p := NewNothing() index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -34,19 +34,21 @@ func TestNothingIndex(t *testing.T) { } func BenchmarkIndexNothing(b *testing.B) { - m := Nothing{} + m := NewNothing() for i := 0; i < b.N; i++ { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } } func BenchmarkIndexNothingParallel(b *testing.B) { - m := Nothing{} + m := NewNothing() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - m.Index(bench_pattern) + _, s := m.Index(bench_pattern) + releaseSegments(s) } }) } diff --git a/match/prefix.go b/match/prefix.go index 429ff88..a734725 100644 --- a/match/prefix.go +++ b/match/prefix.go @@ -10,6 +10,10 @@ type Prefix struct { Prefix string } +func NewPrefix(p string) Prefix { + return Prefix{p} +} + func (self Prefix) Index(s string) (int, []int) { idx := strings.Index(s, self.Prefix) if idx == -1 { diff --git a/match/prefix_suffix.go b/match/prefix_suffix.go index 620b873..8208085 100644 --- a/match/prefix_suffix.go +++ b/match/prefix_suffix.go @@ -9,6 +9,10 @@ type PrefixSuffix struct { Prefix, Suffix string } +func NewPrefixSuffix(p, s string) PrefixSuffix { + return PrefixSuffix{p, s} +} + func (self PrefixSuffix) Index(s string) (int, []int) { prefixIdx := strings.Index(s, self.Prefix) if prefixIdx == -1 { @@ -16,11 +20,14 @@ func (self PrefixSuffix) Index(s string) (int, []int) { } suffixLen := len(self.Suffix) - if suffixLen <= 0 { return prefixIdx, []int{len(s) - prefixIdx} } + if (len(s) - prefixIdx) <= 0 { + return -1, nil + } + segments := acquireSegments(len(s) - prefixIdx) for sub := s[prefixIdx:]; ; { suffixIdx := strings.LastIndex(sub, self.Suffix) @@ -33,7 +40,8 @@ func (self PrefixSuffix) Index(s string) (int, []int) { } if len(segments) == 0 { - return -1, segments + releaseSegments(segments) + return -1, nil } reverseSegments(segments) diff --git a/match/prefix_suffix_test.go b/match/prefix_suffix_test.go index aaf5dca..79b17b2 100644 --- a/match/prefix_suffix_test.go +++ b/match/prefix_suffix_test.go @@ -35,7 +35,7 @@ func TestPrefixSuffixIndex(t *testing.T) { []int{3}, }, } { - p := PrefixSuffix{test.prefix, test.suffix} + p := NewPrefixSuffix(test.prefix, test.suffix) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -47,7 +47,7 @@ func TestPrefixSuffixIndex(t *testing.T) { } func BenchmarkIndexPrefixSuffix(b *testing.B) { - m := PrefixSuffix{"qew", "sqw"} + m := NewPrefixSuffix("qew", "sqw") for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -56,7 +56,7 @@ func BenchmarkIndexPrefixSuffix(b *testing.B) { } func BenchmarkIndexPrefixSuffixParallel(b *testing.B) { - m := PrefixSuffix{"qew", "sqw"} + m := NewPrefixSuffix("qew", "sqw") b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/prefix_test.go b/match/prefix_test.go index f6b2f04..22a296e 100644 --- a/match/prefix_test.go +++ b/match/prefix_test.go @@ -25,7 +25,7 @@ func TestPrefixIndex(t *testing.T) { []int{2, 3, 4, 5}, }, } { - p := Prefix{test.prefix} + p := NewPrefix(test.prefix) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,7 +37,7 @@ func TestPrefixIndex(t *testing.T) { } func BenchmarkIndexPrefix(b *testing.B) { - m := Prefix{"qew"} + m := NewPrefix("qew") for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -46,7 +46,7 @@ func BenchmarkIndexPrefix(b *testing.B) { } func BenchmarkIndexPrefixParallel(b *testing.B) { - m := Prefix{"qew"} + m := NewPrefix("qew") b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/range.go b/match/range.go index 8a90569..ce30245 100644 --- a/match/range.go +++ b/match/range.go @@ -10,6 +10,10 @@ type Range struct { Not bool } +func NewRange(lo, hi rune, not bool) Range { + return Range{lo, hi, not} +} + func (self Range) Len() int { return lenOne } diff --git a/match/range_test.go b/match/range_test.go index 1bde746..0dddcfd 100644 --- a/match/range_test.go +++ b/match/range_test.go @@ -35,7 +35,7 @@ func TestRangeIndex(t *testing.T) { []int{1}, }, } { - m := Range{test.lo, test.hi, test.not} + m := NewRange(test.lo, test.hi, test.not) index, segments := m.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -47,7 +47,7 @@ func TestRangeIndex(t *testing.T) { } func BenchmarkIndexRange(b *testing.B) { - m := Range{'0', '9', false} + m := NewRange('0', '9', false) for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -56,7 +56,7 @@ func BenchmarkIndexRange(b *testing.B) { } func BenchmarkIndexRangeParallel(b *testing.B) { - m := Range{'0', '9', false} + m := NewRange('0', '9', false) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/row.go b/match/row.go index a836a5c..d0dcb35 100644 --- a/match/row.go +++ b/match/row.go @@ -10,9 +10,9 @@ type Row struct { Segments []int } -func NewRow(m Matchers, len int) Row { +func NewRow(len int, m ...Matcher) Row { return Row{ - Matchers: m, + Matchers: Matchers(m), RunesLength: len, Segments: []int{len}, } @@ -68,8 +68,6 @@ func (self Row) Index(s string) (int, []int) { for i := range s { // this is not strict check but useful - // when glob will be refactored for usage with []rune - // it will be better if len(s[i:]) < self.RunesLength { break } diff --git a/match/row_test.go b/match/row_test.go index 0bd7bd8..c9e65ef 100644 --- a/match/row_test.go +++ b/match/row_test.go @@ -17,7 +17,7 @@ func TestRowIndex(t *testing.T) { Matchers{ NewText("abc"), NewText("def"), - Single{}, + NewSingle(nil), }, 7, "qweabcdefghij", @@ -28,7 +28,7 @@ func TestRowIndex(t *testing.T) { Matchers{ NewText("abc"), NewText("def"), - Single{}, + NewSingle(nil), }, 7, "abcd", @@ -36,10 +36,7 @@ func TestRowIndex(t *testing.T) { nil, }, } { - p := Row{ - Matchers: test.matchers, - RunesLength: test.length, - } + p := NewRow(test.length, test.matchers...) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -51,14 +48,14 @@ func TestRowIndex(t *testing.T) { } func BenchmarkRowIndex(b *testing.B) { - m := Row{ - Matchers: Matchers{ + m := NewRow( + 7, + Matchers{ NewText("abc"), NewText("def"), - Single{}, - }, - RunesLength: 7, - } + NewSingle(nil), + }..., + ) for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -67,14 +64,14 @@ func BenchmarkRowIndex(b *testing.B) { } func BenchmarkIndexRowParallel(b *testing.B) { - m := Row{ - Matchers: Matchers{ + m := NewRow( + 7, + Matchers{ NewText("abc"), NewText("def"), - Single{}, - }, - RunesLength: 7, - } + NewSingle(nil), + }..., + ) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/single.go b/match/single.go index 6911edf..33e926d 100644 --- a/match/single.go +++ b/match/single.go @@ -11,6 +11,10 @@ type Single struct { Separators []rune } +func NewSingle(s []rune) Single { + return Single{s} +} + func (self Single) Match(s string) bool { r, w := utf8.DecodeRuneInString(s) if len(s) > w { @@ -35,5 +39,5 @@ func (self Single) Index(s string) (int, []int) { } func (self Single) String() string { - return fmt.Sprintf("", self.Separators) + return fmt.Sprintf("", string(self.Separators)) } diff --git a/match/single_test.go b/match/single_test.go index b08f236..a62d720 100644 --- a/match/single_test.go +++ b/match/single_test.go @@ -25,7 +25,7 @@ func TestSingleIndex(t *testing.T) { nil, }, } { - p := Single{test.separators} + p := NewSingle(test.separators) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,7 +37,7 @@ func TestSingleIndex(t *testing.T) { } func BenchmarkIndexSingle(b *testing.B) { - m := Single{bench_separators} + m := NewSingle(bench_separators) for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -46,7 +46,7 @@ func BenchmarkIndexSingle(b *testing.B) { } func BenchmarkIndexSingleParallel(b *testing.B) { - m := Single{bench_separators} + m := NewSingle(bench_separators) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/suffix.go b/match/suffix.go index d38d71a..85bea8c 100644 --- a/match/suffix.go +++ b/match/suffix.go @@ -9,13 +9,8 @@ type Suffix struct { Suffix string } -func (self Suffix) Index(s string) (int, []int) { - idx := strings.Index(s, self.Suffix) - if idx == -1 { - return -1, nil - } - - return 0, []int{idx + len(self.Suffix)} +func NewSuffix(s string) Suffix { + return Suffix{s} } func (self Suffix) Len() int { @@ -26,6 +21,15 @@ func (self Suffix) Match(s string) bool { return strings.HasSuffix(s, self.Suffix) } +func (self Suffix) Index(s string) (int, []int) { + idx := strings.Index(s, self.Suffix) + if idx == -1 { + return -1, nil + } + + return 0, []int{idx + len(self.Suffix)} +} + func (self Suffix) String() string { return fmt.Sprintf("", self.Suffix) } diff --git a/match/suffix_test.go b/match/suffix_test.go index 3e3c250..4904763 100644 --- a/match/suffix_test.go +++ b/match/suffix_test.go @@ -25,7 +25,7 @@ func TestSuffixIndex(t *testing.T) { []int{5}, }, } { - p := Suffix{test.prefix} + p := NewSuffix(test.prefix) index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -37,7 +37,7 @@ func TestSuffixIndex(t *testing.T) { } func BenchmarkIndexSuffix(b *testing.B) { - m := Suffix{"qwe"} + m := NewSuffix("qwe") for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -46,7 +46,7 @@ func BenchmarkIndexSuffix(b *testing.B) { } func BenchmarkIndexSuffixParallel(b *testing.B) { - m := Suffix{"qwe"} + m := NewSuffix("qwe") b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/super.go b/match/super.go index e7f1aec..3875950 100644 --- a/match/super.go +++ b/match/super.go @@ -6,6 +6,10 @@ import ( type Super struct{} +func NewSuper() Super { + return Super{} +} + func (self Super) Match(s string) bool { return true } @@ -15,8 +19,7 @@ func (self Super) Len() int { } func (self Super) Index(s string) (int, []int) { - //todo acquire here - segments := make([]int, 0, len(s)+1) + segments := acquireSegments(len(s) + 1) for i := range s { segments = append(segments, i) } diff --git a/match/super_test.go b/match/super_test.go index e7c2624..10418dc 100644 --- a/match/super_test.go +++ b/match/super_test.go @@ -22,7 +22,7 @@ func TestSuperIndex(t *testing.T) { []int{0}, }, } { - p := Super{} + p := NewSuper() index, segments := p.Index(test.fixture) if index != test.index { t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) @@ -34,7 +34,7 @@ func TestSuperIndex(t *testing.T) { } func BenchmarkIndexSuper(b *testing.B) { - m := Super{} + m := NewSuper() for i := 0; i < b.N; i++ { _, s := m.Index(bench_pattern) @@ -43,7 +43,7 @@ func BenchmarkIndexSuper(b *testing.B) { } func BenchmarkIndexSuperParallel(b *testing.B) { - m := Super{} + m := NewSuper() b.RunParallel(func(pb *testing.PB) { for pb.Next() {