Use of constuctors every where, optimizations

This commit is contained in:
gobwas 2016-02-24 12:36:15 +03:00
parent f884dfeb2e
commit 34494ea116
33 changed files with 341 additions and 267 deletions

View File

@ -14,7 +14,7 @@ func optimize(matcher match.Matcher) match.Matcher {
case match.Any: case match.Any:
if len(m.Separators) == 0 { if len(m.Separators) == 0 {
return match.Super{} return match.NewSuper()
} }
case match.AnyOf: case match.AnyOf:
@ -54,23 +54,23 @@ func optimize(matcher match.Matcher) match.Matcher {
rs, rightSuffix := m.Right.(match.Suffix) rs, rightSuffix := m.Right.(match.Suffix)
if leftSuper && rightSuper { if leftSuper && rightSuper {
return match.Contains{r.Str, false} return match.NewContains(r.Str, false)
} }
if leftSuper && rightNil { if leftSuper && rightNil {
return match.Suffix{r.Str} return match.NewSuffix(r.Str)
} }
if rightSuper && leftNil { if rightSuper && leftNil {
return match.Prefix{r.Str} return match.NewPrefix(r.Str)
} }
if leftNil && rightSuffix { if leftNil && rightSuffix {
return match.PrefixSuffix{Prefix: r.Str, Suffix: rs.Suffix} return match.NewPrefixSuffix(r.Str, rs.Suffix)
} }
if rightNil && leftPrefix { if rightNil && leftPrefix {
return match.PrefixSuffix{Prefix: lp.Prefix, Suffix: r.Str} return match.NewPrefixSuffix(lp.Prefix, r.Str)
} }
return m 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 { func glueAsEvery(matchers []match.Matcher) match.Matcher {
@ -182,29 +182,29 @@ func glueAsEvery(matchers []match.Matcher) match.Matcher {
} }
if hasSuper && !hasAny && !hasSingle { if hasSuper && !hasAny && !hasSingle {
return match.Super{} return match.NewSuper()
} }
if hasAny && !hasSuper && !hasSingle { if hasAny && !hasSuper && !hasSingle {
return match.Any{separator} return match.NewAny(separator)
} }
if (hasAny || hasSuper) && min > 0 && len(separator) == 0 { 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 { if min > 0 {
every.Add(match.Min{min}) every.Add(match.NewMin(min))
if !hasAny && !hasSuper { if !hasAny && !hasSuper {
every.Add(match.Max{min}) every.Add(match.NewMax(min))
} }
} }
if len(separator) > 0 { if len(separator) > 0 {
every.Add(match.Contains{string(separator), true}) every.Add(match.NewContains(string(separator), true))
} }
return every return every
@ -474,7 +474,7 @@ func doAnyOf(n *nodeAnyOf, s []rune) (match.Matcher, error) {
var matchers []match.Matcher var matchers []match.Matcher
for _, desc := range n.children() { for _, desc := range n.children() {
if desc == nil { if desc == nil {
matchers = append(matchers, match.Nothing{}) matchers = append(matchers, match.NewNothing())
continue continue
} }
@ -485,7 +485,7 @@ func doAnyOf(n *nodeAnyOf, s []rune) (match.Matcher, error) {
matchers = append(matchers, optimize(m)) 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) { 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 var matchers []match.Matcher
for _, desc := range n.children() { for _, desc := range n.children() {
if desc == nil { if desc == nil {
matchers = append(matchers, match.Nothing{}) matchers = append(matchers, match.NewNothing())
continue continue
} }
@ -511,12 +511,12 @@ func do(leaf node, s []rune) (m match.Matcher, err error) {
matchers = append(matchers, optimize(m)) matchers = append(matchers, optimize(m))
} }
return match.AnyOf{matchers}, nil return match.NewAnyOf(matchers...), nil
case *nodePattern: case *nodePattern:
nodes := leaf.children() nodes := leaf.children()
if len(nodes) == 0 { if len(nodes) == 0 {
return match.Nothing{}, nil return match.NewNothing(), nil
} }
var matchers []match.Matcher var matchers []match.Matcher
@ -534,19 +534,19 @@ func do(leaf node, s []rune) (m match.Matcher, err error) {
} }
case *nodeList: case *nodeList:
m = match.List{[]rune(n.chars), n.not} m = match.NewList([]rune(n.chars), n.not)
case *nodeRange: case *nodeRange:
m = match.Range{n.lo, n.hi, n.not} m = match.NewRange(n.lo, n.hi, n.not)
case *nodeAny: case *nodeAny:
m = match.Any{s} m = match.NewAny(s)
case *nodeSuper: case *nodeSuper:
m = match.Super{} m = match.NewSuper()
case *nodeSingle: case *nodeSingle:
m = match.Single{s} m = match.NewSingle(s)
case *nodeText: case *nodeText:
m = match.NewText(n.text) m = match.NewText(n.text)
@ -633,19 +633,19 @@ func do2(node node, s []rune) ([]match.Matcher, error) {
} }
case *nodeList: case *nodeList:
result = append(result, match.List{[]rune(n.chars), n.not}) result = append(result, match.NewList([]rune(n.chars), n.not))
case *nodeRange: 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: case *nodeAny:
result = append(result, match.Any{s}) result = append(result, match.NewAny(s))
case *nodeSuper: case *nodeSuper:
result = append(result, match.Super{}) result = append(result, match.NewSuper())
case *nodeSingle: case *nodeSingle:
result = append(result, match.Single{s}) result = append(result, match.NewSingle(s))
case *nodeText: case *nodeText:
result = append(result, match.NewText(n.text)) result = append(result, match.NewText(n.text))
@ -669,7 +669,7 @@ func compile(ast *nodePattern, s []rune) (Glob, error) {
// if len(ms) == 1 { // if len(ms) == 1 {
// return ms[0], nil // return ms[0], nil
// } else { // } else {
// return match.AnyOf{ms}, nil // return match.NewAnyOf(ms), nil
// } // }
g, err := do(ast, s) g, err := do(ast, s)

View File

@ -15,40 +15,40 @@ func TestGlueMatchers(t *testing.T) {
}{ }{
{ {
[]match.Matcher{ []match.Matcher{
match.Super{}, match.NewSuper(),
match.Single{}, match.NewSingle(nil),
}, },
match.Min{1}, match.NewMin(1),
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.Any{separators}, match.NewAny(separators),
match.Single{separators}, match.NewSingle(separators),
}, },
match.EveryOf{match.Matchers{ match.EveryOf{match.Matchers{
match.Min{1}, match.NewMin(1),
match.Contains{string(separators), true}, match.NewContains(string(separators), true),
}}, }},
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.Single{}, match.NewSingle(nil),
match.Single{}, match.NewSingle(nil),
match.Single{}, match.NewSingle(nil),
}, },
match.EveryOf{match.Matchers{ match.EveryOf{match.Matchers{
match.Min{3}, match.NewMin(3),
match.Max{3}, match.NewMax(3),
}}, }},
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.List{[]rune{'a'}, true}, match.NewList([]rune{'a'}, true),
match.Any{[]rune{'a'}}, match.NewAny([]rune{'a'}),
}, },
match.EveryOf{match.Matchers{ match.EveryOf{match.Matchers{
match.Min{1}, match.NewMin(1),
match.Contains{"a", true}, match.NewContains("a", true),
}}, }},
}, },
} { } {
@ -59,7 +59,7 @@ func TestGlueMatchers(t *testing.T) {
} }
if !reflect.DeepEqual(act, test.exp) { 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 continue
} }
} }
@ -72,15 +72,15 @@ func TestCompileMatchers(t *testing.T) {
}{ }{
{ {
[]match.Matcher{ []match.Matcher{
match.Super{}, match.NewSuper(),
match.Single{separators}, match.NewSingle(separators),
match.NewText("c"), match.NewText("c"),
}, },
match.NewBTree( match.NewBTree(
match.NewText("c"), match.NewText("c"),
match.NewBTree( match.NewBTree(
match.Single{separators}, match.NewSingle(separators),
match.Super{}, match.NewSuper(),
nil, nil,
), ),
nil, nil,
@ -88,32 +88,32 @@ func TestCompileMatchers(t *testing.T) {
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.Any{}, match.NewAny(nil),
match.NewText("c"), match.NewText("c"),
match.Any{}, match.NewAny(nil),
}, },
match.NewBTree( match.NewBTree(
match.NewText("c"), match.NewText("c"),
match.Any{}, match.NewAny(nil),
match.Any{}, match.NewAny(nil),
), ),
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.Range{'a', 'c', true}, match.NewRange('a', 'c', true),
match.List{[]rune{'z', 't', 'e'}, false}, match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
match.Single{}, match.NewSingle(nil),
}, },
match.Row{ match.NewRow(
Matchers: match.Matchers{ 4,
match.Range{'a', 'c', true}, match.Matchers{
match.List{[]rune{'z', 't', 'e'}, false}, match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
match.Single{}, match.NewSingle(nil),
}, }...,
RunesLength: 4, ),
},
}, },
} { } {
act, err := compileMatchers(test.in) act, err := compileMatchers(test.in)
@ -123,7 +123,7 @@ func TestCompileMatchers(t *testing.T) {
} }
if !reflect.DeepEqual(act, test.exp) { 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 continue
} }
} }
@ -135,52 +135,52 @@ func TestConvertMatchers(t *testing.T) {
}{ }{
{ {
[]match.Matcher{ []match.Matcher{
match.Range{'a', 'c', true}, match.NewRange('a', 'c', true),
match.List{[]rune{'z', 't', 'e'}, false}, match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
match.Single{}, match.NewSingle(nil),
match.Any{}, match.NewAny(nil),
}, },
[]match.Matcher{ []match.Matcher{
match.Row{ match.NewRow(
Matchers: match.Matchers{ 4,
match.Range{'a', 'c', true}, []match.Matcher{
match.List{[]rune{'z', 't', 'e'}, false}, match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
match.Single{}, match.NewSingle(nil),
}, }...,
RunesLength: 4, ),
}, match.NewAny(nil),
match.Any{},
}, },
}, },
{ {
[]match.Matcher{ []match.Matcher{
match.Range{'a', 'c', true}, match.NewRange('a', 'c', true),
match.List{[]rune{'z', 't', 'e'}, false}, match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
match.Single{}, match.NewSingle(nil),
match.Any{}, match.NewAny(nil),
match.Single{}, match.NewSingle(nil),
match.Single{}, match.NewSingle(nil),
match.Any{}, match.NewAny(nil),
}, },
[]match.Matcher{ []match.Matcher{
match.Row{ match.NewRow(
Matchers: match.Matchers{ 3,
match.Range{'a', 'c', true}, match.Matchers{
match.List{[]rune{'z', 't', 'e'}, false}, match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"), match.NewText("c"),
}, }...,
RunesLength: 3, ),
}, match.NewMin(3),
match.Min{3},
}, },
}, },
} { } {
act := minimizeMatchers(test.in) act := minimizeMatchers(test.in)
if !reflect.DeepEqual(act, test.exp) { 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 continue
} }
} }
@ -213,20 +213,20 @@ func TestCompiler(t *testing.T) {
{ {
ast: pattern(&nodeAny{}), ast: pattern(&nodeAny{}),
sep: separators, sep: separators,
result: match.Any{separators}, result: match.NewAny(separators),
}, },
{ {
ast: pattern(&nodeAny{}), ast: pattern(&nodeAny{}),
result: match.Super{}, result: match.NewSuper(),
}, },
{ {
ast: pattern(&nodeSuper{}), ast: pattern(&nodeSuper{}),
result: match.Super{}, result: match.NewSuper(),
}, },
{ {
ast: pattern(&nodeSingle{}), ast: pattern(&nodeSingle{}),
sep: separators, sep: separators,
result: match.Single{separators}, result: match.NewSingle(separators),
}, },
{ {
ast: pattern(&nodeRange{ ast: pattern(&nodeRange{
@ -234,39 +234,39 @@ func TestCompiler(t *testing.T) {
hi: 'z', hi: 'z',
not: true, not: true,
}), }),
result: match.Range{'a', 'z', true}, result: match.NewRange('a', 'z', true),
}, },
{ {
ast: pattern(&nodeList{ ast: pattern(&nodeList{
chars: "abc", chars: "abc",
not: true, not: true,
}), }),
result: match.List{[]rune{'a', 'b', 'c'}, true}, result: match.NewList([]rune{'a', 'b', 'c'}, true),
}, },
{ {
ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}), ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}),
sep: separators, sep: separators,
result: match.EveryOf{Matchers: match.Matchers{ result: match.EveryOf{Matchers: match.Matchers{
match.Min{3}, match.NewMin(3),
match.Contains{string(separators), true}, match.NewContains(string(separators), true),
}}, }},
}, },
{ {
ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}), ast: pattern(&nodeAny{}, &nodeSingle{}, &nodeSingle{}, &nodeSingle{}),
result: match.Min{3}, result: match.NewMin(3),
}, },
{ {
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}, &nodeSingle{}), ast: pattern(&nodeAny{}, &nodeText{text: "abc"}, &nodeSingle{}),
sep: separators, sep: separators,
result: match.NewBTree( result: match.NewBTree(
match.Row{ match.NewRow(
Matchers: match.Matchers{ 4,
match.Matchers{
match.NewText("abc"), match.NewText("abc"),
match.Single{separators}, match.NewSingle(separators),
}, }...,
RunesLength: 4, ),
}, match.NewAny(separators),
match.Any{separators},
nil, nil,
), ),
}, },
@ -274,49 +274,49 @@ func TestCompiler(t *testing.T) {
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSingle{}), ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSingle{}),
sep: separators, sep: separators,
result: match.NewBTree( result: match.NewBTree(
match.Row{ match.NewRow(
Matchers: match.Matchers{ 5,
match.Single{separators}, match.Matchers{
match.NewSingle(separators),
match.NewText("abc"), match.NewText("abc"),
match.Single{separators}, match.NewSingle(separators),
}, }...,
RunesLength: 5, ),
}, match.NewSuper(),
match.Super{},
nil, nil,
), ),
}, },
{ {
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}), ast: pattern(&nodeAny{}, &nodeText{text: "abc"}),
result: match.Suffix{"abc"}, result: match.NewSuffix("abc"),
}, },
{ {
ast: pattern(&nodeText{text: "abc"}, &nodeAny{}), ast: pattern(&nodeText{text: "abc"}, &nodeAny{}),
result: match.Prefix{"abc"}, result: match.NewPrefix("abc"),
}, },
{ {
ast: pattern(&nodeText{text: "abc"}, &nodeAny{}, &nodeText{text: "def"}), 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{}), 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{}), ast: pattern(&nodeAny{}, &nodeAny{}, &nodeAny{}, &nodeText{text: "abc"}, &nodeAny{}, &nodeAny{}),
sep: separators, sep: separators,
result: match.NewBTree( result: match.NewBTree(
match.NewText("abc"), match.NewText("abc"),
match.Any{separators}, match.NewAny(separators),
match.Any{separators}, match.NewAny(separators),
), ),
}, },
{ {
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSuper{}, &nodeSingle{}), ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSuper{}, &nodeSingle{}),
result: match.NewBTree( result: match.NewBTree(
match.NewText("abc"), match.NewText("abc"),
match.Min{1}, match.NewMin(1),
match.Min{1}, match.NewMin(1),
), ),
}, },
{ {
@ -348,9 +348,9 @@ func TestCompiler(t *testing.T) {
match.NewText("abc"), match.NewText("abc"),
nil, nil,
match.AnyOf{Matchers: match.Matchers{ match.AnyOf{Matchers: match.Matchers{
match.Single{}, match.NewSingle(nil),
match.List{List: []rune{'d', 'e', 'f'}}, match.NewList([]rune{'d', 'e', 'f'}, false),
match.Nothing{}, match.NewNothing(),
}}, }},
), ),
}, },
@ -361,15 +361,15 @@ func TestCompiler(t *testing.T) {
&nodeAny{}, &nodeAny{},
), ),
result: match.NewBTree( result: match.NewBTree(
match.Row{ match.NewRow(
Matchers: match.Matchers{ 2,
match.Range{Lo: 'a', Hi: 'z'}, match.Matchers{
match.Range{Lo: 'a', Hi: 'x', Not: true}, match.NewRange('a', 'z', false),
}, match.NewRange('a', 'x', true),
RunesLength: 2, }...,
}, ),
nil, nil,
match.Super{}, match.NewSuper(),
), ),
}, },
{ {
@ -385,17 +385,17 @@ func TestCompiler(t *testing.T) {
&nodeText{text: "ghi"}, &nodeText{text: "ghi"},
), ),
)), )),
result: match.Row{ result: match.NewRow(
RunesLength: 7, 7,
Matchers: match.Matchers{ match.Matchers{
match.NewText("abc"), match.NewText("abc"),
match.AnyOf{Matchers: match.Matchers{ match.AnyOf{Matchers: match.Matchers{
match.List{List: []rune{'a', 'b', 'c'}}, match.NewList([]rune{'a', 'b', 'c'}, false),
match.List{List: []rune{'d', 'e', 'f'}}, match.NewList([]rune{'d', 'e', 'f'}, false),
}}, }},
match.NewText("ghi"), match.NewText("ghi"),
}, }...,
}, ),
}, },
// { // {
// ast: pattern( // ast: pattern(
@ -403,21 +403,21 @@ func TestCompiler(t *testing.T) {
// anyOf(&nodeText{text: "c"}, &nodeText{text: "d"}), // anyOf(&nodeText{text: "c"}, &nodeText{text: "d"}),
// ), // ),
// result: match.AnyOf{Matchers: match.Matchers{ // result: match.AnyOf{Matchers: match.Matchers{
// match.Row{Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"c", 1}}}, // match.NewRow(Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"c", 1}}),
// match.Row{Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"d"}}}, // match.NewRow(Matchers: match.Matchers{match.Raw{"a"}, match.Raw{"d"}}),
// match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"c", 1}}}, // match.NewRow(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{"b"}, match.Raw{"d"}}),
// }}, // }},
// }, // },
} { } {
prog, err := compile(test.ast, test.sep) m, err := compile(test.ast, test.sep)
if err != nil { if err != nil {
t.Errorf("compilation error: %s", err) t.Errorf("compilation error: %s", err)
continue continue
} }
if !reflect.DeepEqual(prog, test.result) { if !reflect.DeepEqual(m, test.result) {
t.Errorf("#%d results are not equal:\nexp: %s,\nact: %s", id, test.result, prog) t.Errorf("#%d results are not equal:\nexp: %#v\nact: %#v", id, test.result, m)
continue continue
} }
} }
@ -426,105 +426,105 @@ func TestCompiler(t *testing.T) {
const complexityString = "abcd" const complexityString = "abcd"
//func BenchmarkComplexityAny(b *testing.B) { //func BenchmarkComplexityAny(b *testing.B) {
// m := match.Any{} // m := match.NewAny(nil)
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityContains(b *testing.B) { //func BenchmarkComplexityContains(b *testing.B) {
// m := match.Contains{} // m := match.NewContains()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityList(b *testing.B) { //func BenchmarkComplexityList(b *testing.B) {
// m := match.List{} // m := match.NewList()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityMax(b *testing.B) { //func BenchmarkComplexityMax(b *testing.B) {
// m := match.Max{} // m := match.NewMax()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityMin(b *testing.B) { //func BenchmarkComplexityMin(b *testing.B) {
// m := match.Min{} // m := match.NewMin()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityNothing(b *testing.B) { //func BenchmarkComplexityNothing(b *testing.B) {
// m := match.Nothing{} // m := match.NewNothing()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityPrefix(b *testing.B) { //func BenchmarkComplexityPrefix(b *testing.B) {
// m := match.Prefix{} // m := match.NewPrefix()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityPrefixSuffix(b *testing.B) { //func BenchmarkComplexityPrefixSuffix(b *testing.B) {
// m := match.PrefixSuffix{} // m := match.NewPrefixSuffix()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityRange(b *testing.B) { //func BenchmarkComplexityRange(b *testing.B) {
// m := match.Range{} // m := match.NewRange()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityRow(b *testing.B) { //func BenchmarkComplexityRow(b *testing.B) {
// m := match.Row{} // m := match.NewRow()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexitySingle(b *testing.B) { //func BenchmarkComplexitySingle(b *testing.B) {
// m := match.Single{} // m := match.NewSingle(nil)
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexitySuffix(b *testing.B) { //func BenchmarkComplexitySuffix(b *testing.B) {
// m := match.Suffix{} // m := match.NewSuffix()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexitySuper(b *testing.B) { //func BenchmarkComplexitySuper(b *testing.B) {
// m := match.Super{} // m := match.NewSuper()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityText(b *testing.B) { //func BenchmarkComplexityText(b *testing.B) {
// m := match.Text{} // m := match.NewText()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
// } // }
//} //}
//func BenchmarkComplexityAnyOf(b *testing.B) { //func BenchmarkComplexityAnyOf(b *testing.B) {
// m := match.AnyOf{} // m := match.NewAnyOf()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)
@ -538,7 +538,7 @@ const complexityString = "abcd"
// } // }
//} //}
//func BenchmarkComplexityEveryOf(b *testing.B) { //func BenchmarkComplexityEveryOf(b *testing.B) {
// m := match.EveryOf{} // m := match.NewEveryOf()
// for i := 0; i < b.N; i++ { // for i := 0; i < b.N; i++ {
// _ = m.Match(complexityString) // _ = m.Match(complexityString)
// _, _ = m.Index(complexityString) // _, _ = m.Index(complexityString)

View File

@ -9,6 +9,10 @@ type Any struct {
Separators []rune Separators []rune
} }
func NewAny(s []rune) Any {
return Any{s}
}
func (self Any) Match(s string) bool { func (self Any) Match(s string) bool {
return strings.IndexAnyRunes(s, self.Separators) == -1 return strings.IndexAnyRunes(s, self.Separators) == -1
} }

View File

@ -8,6 +8,10 @@ type AnyOf struct {
Matchers Matchers Matchers Matchers
} }
func NewAnyOf(m ...Matcher) AnyOf {
return AnyOf{Matchers(m)}
}
func (self *AnyOf) Add(m Matcher) error { func (self *AnyOf) Add(m Matcher) error {
self.Matchers = append(self.Matchers, m) self.Matchers = append(self.Matchers, m)
return nil return nil
@ -27,7 +31,6 @@ func (self AnyOf) Index(s string) (int, []int) {
index := -1 index := -1
segments := acquireSegments(len(s)) segments := acquireSegments(len(s))
for _, m := range self.Matchers { for _, m := range self.Matchers {
idx, seg := m.Index(s) idx, seg := m.Index(s)
if idx == -1 { if idx == -1 {

View File

@ -14,7 +14,7 @@ func TestAnyOfIndex(t *testing.T) {
}{ }{
{ {
Matchers{ Matchers{
Any{}, NewAny(nil),
NewText("b"), NewText("b"),
NewText("c"), NewText("c"),
}, },
@ -24,8 +24,8 @@ func TestAnyOfIndex(t *testing.T) {
}, },
{ {
Matchers{ Matchers{
Prefix{"b"}, NewPrefix("b"),
Suffix{"c"}, NewSuffix("c"),
}, },
"abc", "abc",
0, 0,
@ -41,7 +41,7 @@ func TestAnyOfIndex(t *testing.T) {
[]int{1}, []int{1},
}, },
} { } {
everyOf := AnyOf{test.matchers} everyOf := NewAnyOf(test.matchers...)
index, segments := everyOf.Index(test.fixture) index, segments := everyOf.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)

View File

@ -25,7 +25,7 @@ func TestAnyIndex(t *testing.T) {
[]int{0, 1, 2, 3}, []int{0, 1, 2, 3},
}, },
} { } {
p := Any{test.sep} p := NewAny(test.sep)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexAny(b *testing.B) {
m := Any{bench_separators} m := NewAny(bench_separators)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -46,7 +46,7 @@ func BenchmarkIndexAny(b *testing.B) {
} }
func BenchmarkIndexAnyParallel(b *testing.B) { func BenchmarkIndexAnyParallel(b *testing.B) {
m := Any{bench_separators} m := NewAny(bench_separators)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -129,5 +129,18 @@ func (self BTree) Match(s string) bool {
} }
func (self BTree) String() string { func (self BTree) String() string {
return fmt.Sprintf("<btree:[%s<-%s->%s]>", self.Left, self.Value, self.Right) const n string = "<nil>"
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("<btree:[%s<-%s->%s]>", l, self.Value, r)
} }

View File

@ -11,17 +11,17 @@ func TestBTree(t *testing.T) {
exp bool exp bool
}{ }{
{ {
NewBTree(NewText("abc"), Super{}, Super{}), NewBTree(NewText("abc"), NewSuper(), NewSuper()),
"abc", "abc",
true, true,
}, },
{ {
NewBTree(NewText("a"), Single{}, Single{}), NewBTree(NewText("a"), NewSingle(nil), NewSingle(nil)),
"aaa", "aaa",
true, true,
}, },
{ {
NewBTree(NewText("b"), Single{}, nil), NewBTree(NewText("b"), NewSingle(nil), nil),
"bbb", "bbb",
false, false,
}, },
@ -29,8 +29,8 @@ func TestBTree(t *testing.T) {
NewBTree( NewBTree(
NewText("c"), NewText("c"),
NewBTree( NewBTree(
Single{}, NewSingle(nil),
Super{}, NewSuper(),
nil, nil,
), ),
nil, nil,

View File

@ -10,6 +10,10 @@ type Contains struct {
Not bool Not bool
} }
func NewContains(needle string, not bool) Contains {
return Contains{needle, not}
}
func (self Contains) Match(s string) bool { func (self Contains) Match(s string) bool {
return strings.Contains(s, self.Needle) != self.Not return strings.Contains(s, self.Needle) != self.Not
} }

View File

@ -42,7 +42,7 @@ func TestContainsIndex(t *testing.T) {
[]int{0, 1, 2, 3}, []int{0, 1, 2, 3},
}, },
} { } {
p := Contains{test.prefix, test.not} p := NewContains(test.prefix, test.not)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexContains(b *testing.B) {
m := Contains{string(bench_separators), true} m := NewContains(string(bench_separators), true)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -63,7 +63,7 @@ func BenchmarkIndexContains(b *testing.B) {
} }
func BenchmarkIndexContainsParallel(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) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -8,6 +8,10 @@ type EveryOf struct {
Matchers Matchers Matchers Matchers
} }
func NewEveryOf(m ...Matcher) EveryOf {
return EveryOf{Matchers(m)}
}
func (self *EveryOf) Add(m Matcher) error { func (self *EveryOf) Add(m Matcher) error {
self.Matchers = append(self.Matchers, m) self.Matchers = append(self.Matchers, m)
return nil return nil
@ -31,7 +35,6 @@ func (self EveryOf) Index(s string) (int, []int) {
// make `in` with cap as len(s), // make `in` with cap as len(s),
// cause it is the maximum size of output segments values // cause it is the maximum size of output segments values
//todo opti!!!
next := acquireSegments(len(s)) next := acquireSegments(len(s))
current := 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 { for i, m := range self.Matchers {
idx, seg := m.Index(sub) idx, seg := m.Index(sub)
if idx == -1 { if idx == -1 {
releaseSegments(next)
releaseSegments(current)
return -1, nil return -1, nil
} }
@ -61,6 +66,8 @@ func (self EveryOf) Index(s string) (int, []int) {
} }
if len(next) == 0 { if len(next) == 0 {
releaseSegments(next)
releaseSegments(current)
return -1, nil return -1, nil
} }
@ -72,6 +79,8 @@ func (self EveryOf) Index(s string) (int, []int) {
offset += idx offset += idx
} }
releaseSegments(next)
return index, current return index, current
} }

View File

@ -14,7 +14,7 @@ func TestEveryOfIndex(t *testing.T) {
}{ }{
{ {
Matchers{ Matchers{
Any{}, NewAny(nil),
NewText("b"), NewText("b"),
NewText("c"), NewText("c"),
}, },
@ -24,16 +24,16 @@ func TestEveryOfIndex(t *testing.T) {
}, },
{ {
Matchers{ Matchers{
Any{}, NewAny(nil),
Prefix{"b"}, NewPrefix("b"),
Suffix{"c"}, NewSuffix("c"),
}, },
"abc", "abc",
1, 1,
[]int{2}, []int{2},
}, },
} { } {
everyOf := EveryOf{test.matchers} everyOf := NewEveryOf(test.matchers...)
index, segments := everyOf.Index(test.fixture) index, segments := everyOf.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index) t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)

View File

@ -12,10 +12,7 @@ type List struct {
} }
func NewList(list []rune, not bool) List { func NewList(list []rune, not bool) List {
return List{ return List{list, not}
List: list,
Not: not,
}
} }
func (self List) Match(s string) bool { func (self List) Match(s string) bool {
@ -48,5 +45,5 @@ func (self List) String() string {
not = "!" not = "!"
} }
return fmt.Sprintf("<list:%s[%s]>", not, self.List) return fmt.Sprintf("<list:%s[%s]>", not, string(self.List))
} }

View File

@ -9,6 +9,10 @@ type Max struct {
Limit int Limit int
} }
func NewMax(l int) Max {
return Max{l}
}
func (self Max) Match(s string) bool { func (self Max) Match(s string) bool {
var l int var l int
for range s { for range s {
@ -22,8 +26,7 @@ func (self Max) Match(s string) bool {
} }
func (self Max) Index(s string) (int, []int) { func (self Max) Index(s string) (int, []int) {
segments := make([]int, 0, self.Limit+1) segments := acquireSegments(self.Limit + 1)
segments = append(segments, 0) segments = append(segments, 0)
var count int var count int
for i, r := range s { for i, r := range s {

View File

@ -25,7 +25,7 @@ func TestMaxIndex(t *testing.T) {
[]int{0, 1, 2, 3}, []int{0, 1, 2, 3},
}, },
} { } {
p := Max{test.limit} p := NewMax(test.limit)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexMax(b *testing.B) {
m := Max{10} m := NewMax(10)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
} }
func BenchmarkIndexMaxParallel(b *testing.B) { func BenchmarkIndexMaxParallel(b *testing.B) {
m := Max{10} m := NewMax(10)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
}) })
} }

View File

@ -9,6 +9,10 @@ type Min struct {
Limit int Limit int
} }
func NewMin(l int) Min {
return Min{l}
}
func (self Min) Match(s string) bool { func (self Min) Match(s string) bool {
var l int var l int
for range s { for range s {
@ -24,7 +28,12 @@ func (self Min) Match(s string) bool {
func (self Min) Index(s string) (int, []int) { func (self Min) Index(s string) (int, []int) {
var count 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 { for i, r := range s {
count++ count++
if count >= self.Limit { if count >= self.Limit {

View File

@ -25,7 +25,7 @@ func TestMinIndex(t *testing.T) {
[]int{3, 4}, []int{3, 4},
}, },
} { } {
p := Min{test.limit} p := NewMin(test.limit)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexMin(b *testing.B) {
m := Min{10} m := NewMin(10)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
} }
func BenchmarkIndexMinParallel(b *testing.B) { func BenchmarkIndexMinParallel(b *testing.B) {
m := Min{10} m := NewMin(10)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
}) })
} }

View File

@ -6,6 +6,10 @@ import (
type Nothing struct{} type Nothing struct{}
func NewNothing() Nothing {
return Nothing{}
}
func (self Nothing) Match(s string) bool { func (self Nothing) Match(s string) bool {
return len(s) == 0 return len(s) == 0
} }

View File

@ -22,7 +22,7 @@ func TestNothingIndex(t *testing.T) {
[]int{0}, []int{0},
}, },
} { } {
p := Nothing{} p := NewNothing()
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexNothing(b *testing.B) {
m := Nothing{} m := NewNothing()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
} }
func BenchmarkIndexNothingParallel(b *testing.B) { func BenchmarkIndexNothingParallel(b *testing.B) {
m := Nothing{} m := NewNothing()
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
m.Index(bench_pattern) _, s := m.Index(bench_pattern)
releaseSegments(s)
} }
}) })
} }

View File

@ -10,6 +10,10 @@ type Prefix struct {
Prefix string Prefix string
} }
func NewPrefix(p string) Prefix {
return Prefix{p}
}
func (self Prefix) Index(s string) (int, []int) { func (self Prefix) Index(s string) (int, []int) {
idx := strings.Index(s, self.Prefix) idx := strings.Index(s, self.Prefix)
if idx == -1 { if idx == -1 {

View File

@ -9,6 +9,10 @@ type PrefixSuffix struct {
Prefix, Suffix string Prefix, Suffix string
} }
func NewPrefixSuffix(p, s string) PrefixSuffix {
return PrefixSuffix{p, s}
}
func (self PrefixSuffix) Index(s string) (int, []int) { func (self PrefixSuffix) Index(s string) (int, []int) {
prefixIdx := strings.Index(s, self.Prefix) prefixIdx := strings.Index(s, self.Prefix)
if prefixIdx == -1 { if prefixIdx == -1 {
@ -16,11 +20,14 @@ func (self PrefixSuffix) Index(s string) (int, []int) {
} }
suffixLen := len(self.Suffix) suffixLen := len(self.Suffix)
if suffixLen <= 0 { if suffixLen <= 0 {
return prefixIdx, []int{len(s) - prefixIdx} return prefixIdx, []int{len(s) - prefixIdx}
} }
if (len(s) - prefixIdx) <= 0 {
return -1, nil
}
segments := acquireSegments(len(s) - prefixIdx) segments := acquireSegments(len(s) - prefixIdx)
for sub := s[prefixIdx:]; ; { for sub := s[prefixIdx:]; ; {
suffixIdx := strings.LastIndex(sub, self.Suffix) suffixIdx := strings.LastIndex(sub, self.Suffix)
@ -33,7 +40,8 @@ func (self PrefixSuffix) Index(s string) (int, []int) {
} }
if len(segments) == 0 { if len(segments) == 0 {
return -1, segments releaseSegments(segments)
return -1, nil
} }
reverseSegments(segments) reverseSegments(segments)

View File

@ -35,7 +35,7 @@ func TestPrefixSuffixIndex(t *testing.T) {
[]int{3}, []int{3},
}, },
} { } {
p := PrefixSuffix{test.prefix, test.suffix} p := NewPrefixSuffix(test.prefix, test.suffix)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexPrefixSuffix(b *testing.B) {
m := PrefixSuffix{"qew", "sqw"} m := NewPrefixSuffix("qew", "sqw")
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -56,7 +56,7 @@ func BenchmarkIndexPrefixSuffix(b *testing.B) {
} }
func BenchmarkIndexPrefixSuffixParallel(b *testing.B) { func BenchmarkIndexPrefixSuffixParallel(b *testing.B) {
m := PrefixSuffix{"qew", "sqw"} m := NewPrefixSuffix("qew", "sqw")
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -25,7 +25,7 @@ func TestPrefixIndex(t *testing.T) {
[]int{2, 3, 4, 5}, []int{2, 3, 4, 5},
}, },
} { } {
p := Prefix{test.prefix} p := NewPrefix(test.prefix)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexPrefix(b *testing.B) {
m := Prefix{"qew"} m := NewPrefix("qew")
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -46,7 +46,7 @@ func BenchmarkIndexPrefix(b *testing.B) {
} }
func BenchmarkIndexPrefixParallel(b *testing.B) { func BenchmarkIndexPrefixParallel(b *testing.B) {
m := Prefix{"qew"} m := NewPrefix("qew")
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -10,6 +10,10 @@ type Range struct {
Not bool Not bool
} }
func NewRange(lo, hi rune, not bool) Range {
return Range{lo, hi, not}
}
func (self Range) Len() int { func (self Range) Len() int {
return lenOne return lenOne
} }

View File

@ -35,7 +35,7 @@ func TestRangeIndex(t *testing.T) {
[]int{1}, []int{1},
}, },
} { } {
m := Range{test.lo, test.hi, test.not} m := NewRange(test.lo, test.hi, test.not)
index, segments := m.Index(test.fixture) index, segments := m.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexRange(b *testing.B) {
m := Range{'0', '9', false} m := NewRange('0', '9', false)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -56,7 +56,7 @@ func BenchmarkIndexRange(b *testing.B) {
} }
func BenchmarkIndexRangeParallel(b *testing.B) { func BenchmarkIndexRangeParallel(b *testing.B) {
m := Range{'0', '9', false} m := NewRange('0', '9', false)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -10,9 +10,9 @@ type Row struct {
Segments []int Segments []int
} }
func NewRow(m Matchers, len int) Row { func NewRow(len int, m ...Matcher) Row {
return Row{ return Row{
Matchers: m, Matchers: Matchers(m),
RunesLength: len, RunesLength: len,
Segments: []int{len}, Segments: []int{len},
} }
@ -68,8 +68,6 @@ func (self Row) Index(s string) (int, []int) {
for i := range s { for i := range s {
// this is not strict check but useful // 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 { if len(s[i:]) < self.RunesLength {
break break
} }

View File

@ -17,7 +17,7 @@ func TestRowIndex(t *testing.T) {
Matchers{ Matchers{
NewText("abc"), NewText("abc"),
NewText("def"), NewText("def"),
Single{}, NewSingle(nil),
}, },
7, 7,
"qweabcdefghij", "qweabcdefghij",
@ -28,7 +28,7 @@ func TestRowIndex(t *testing.T) {
Matchers{ Matchers{
NewText("abc"), NewText("abc"),
NewText("def"), NewText("def"),
Single{}, NewSingle(nil),
}, },
7, 7,
"abcd", "abcd",
@ -36,10 +36,7 @@ func TestRowIndex(t *testing.T) {
nil, nil,
}, },
} { } {
p := Row{ p := NewRow(test.length, test.matchers...)
Matchers: test.matchers,
RunesLength: test.length,
}
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkRowIndex(b *testing.B) {
m := Row{ m := NewRow(
Matchers: Matchers{ 7,
Matchers{
NewText("abc"), NewText("abc"),
NewText("def"), NewText("def"),
Single{}, NewSingle(nil),
}, }...,
RunesLength: 7, )
}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -67,14 +64,14 @@ func BenchmarkRowIndex(b *testing.B) {
} }
func BenchmarkIndexRowParallel(b *testing.B) { func BenchmarkIndexRowParallel(b *testing.B) {
m := Row{ m := NewRow(
Matchers: Matchers{ 7,
Matchers{
NewText("abc"), NewText("abc"),
NewText("def"), NewText("def"),
Single{}, NewSingle(nil),
}, }...,
RunesLength: 7, )
}
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -11,6 +11,10 @@ type Single struct {
Separators []rune Separators []rune
} }
func NewSingle(s []rune) Single {
return Single{s}
}
func (self Single) Match(s string) bool { func (self Single) Match(s string) bool {
r, w := utf8.DecodeRuneInString(s) r, w := utf8.DecodeRuneInString(s)
if len(s) > w { if len(s) > w {
@ -35,5 +39,5 @@ func (self Single) Index(s string) (int, []int) {
} }
func (self Single) String() string { func (self Single) String() string {
return fmt.Sprintf("<single:![%s]>", self.Separators) return fmt.Sprintf("<single:![%s]>", string(self.Separators))
} }

View File

@ -25,7 +25,7 @@ func TestSingleIndex(t *testing.T) {
nil, nil,
}, },
} { } {
p := Single{test.separators} p := NewSingle(test.separators)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexSingle(b *testing.B) {
m := Single{bench_separators} m := NewSingle(bench_separators)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -46,7 +46,7 @@ func BenchmarkIndexSingle(b *testing.B) {
} }
func BenchmarkIndexSingleParallel(b *testing.B) { func BenchmarkIndexSingleParallel(b *testing.B) {
m := Single{bench_separators} m := NewSingle(bench_separators)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -9,13 +9,8 @@ type Suffix struct {
Suffix string Suffix string
} }
func (self Suffix) Index(s string) (int, []int) { func NewSuffix(s string) Suffix {
idx := strings.Index(s, self.Suffix) return Suffix{s}
if idx == -1 {
return -1, nil
}
return 0, []int{idx + len(self.Suffix)}
} }
func (self Suffix) Len() int { func (self Suffix) Len() int {
@ -26,6 +21,15 @@ func (self Suffix) Match(s string) bool {
return strings.HasSuffix(s, self.Suffix) 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 { func (self Suffix) String() string {
return fmt.Sprintf("<suffix:%s>", self.Suffix) return fmt.Sprintf("<suffix:%s>", self.Suffix)
} }

View File

@ -25,7 +25,7 @@ func TestSuffixIndex(t *testing.T) {
[]int{5}, []int{5},
}, },
} { } {
p := Suffix{test.prefix} p := NewSuffix(test.prefix)
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexSuffix(b *testing.B) {
m := Suffix{"qwe"} m := NewSuffix("qwe")
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -46,7 +46,7 @@ func BenchmarkIndexSuffix(b *testing.B) {
} }
func BenchmarkIndexSuffixParallel(b *testing.B) { func BenchmarkIndexSuffixParallel(b *testing.B) {
m := Suffix{"qwe"} m := NewSuffix("qwe")
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -6,6 +6,10 @@ import (
type Super struct{} type Super struct{}
func NewSuper() Super {
return Super{}
}
func (self Super) Match(s string) bool { func (self Super) Match(s string) bool {
return true return true
} }
@ -15,8 +19,7 @@ func (self Super) Len() int {
} }
func (self Super) Index(s string) (int, []int) { func (self Super) Index(s string) (int, []int) {
//todo acquire here segments := acquireSegments(len(s) + 1)
segments := make([]int, 0, len(s)+1)
for i := range s { for i := range s {
segments = append(segments, i) segments = append(segments, i)
} }

View File

@ -22,7 +22,7 @@ func TestSuperIndex(t *testing.T) {
[]int{0}, []int{0},
}, },
} { } {
p := Super{} p := NewSuper()
index, segments := p.Index(test.fixture) index, segments := p.Index(test.fixture)
if index != test.index { if index != test.index {
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, 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) { func BenchmarkIndexSuper(b *testing.B) {
m := Super{} m := NewSuper()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, s := m.Index(bench_pattern) _, s := m.Index(bench_pattern)
@ -43,7 +43,7 @@ func BenchmarkIndexSuper(b *testing.B) {
} }
func BenchmarkIndexSuperParallel(b *testing.B) { func BenchmarkIndexSuperParallel(b *testing.B) {
m := Super{} m := NewSuper()
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {