mirror of https://github.com/gobwas/glob.git
Optimizations
This commit is contained in:
parent
af4b301eec
commit
3995275190
47
compiler.go
47
compiler.go
|
@ -26,7 +26,7 @@ func optimize(matcher match.Matcher) match.Matcher {
|
||||||
rightNil := m.Right == nil
|
rightNil := m.Right == nil
|
||||||
|
|
||||||
if leftNil && rightNil {
|
if leftNil && rightNil {
|
||||||
return match.Raw{r.Str}
|
return match.NewRaw(r.Str)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, leftSuper := m.Left.(match.Super)
|
_, leftSuper := m.Left.(match.Super)
|
||||||
|
@ -93,15 +93,20 @@ func glueAsRow(matchers []match.Matcher) match.Matcher {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
row := match.Row{}
|
var (
|
||||||
|
c []match.Matcher
|
||||||
|
l int
|
||||||
|
)
|
||||||
for _, matcher := range matchers {
|
for _, matcher := range matchers {
|
||||||
err := row.Add(matcher)
|
if ml := matcher.Len(); ml == -1 {
|
||||||
if err != nil {
|
|
||||||
return nil
|
return nil
|
||||||
|
} else {
|
||||||
|
c = append(c, matcher)
|
||||||
|
l += ml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return row
|
return match.Row{c, l}
|
||||||
}
|
}
|
||||||
|
|
||||||
func glueAsEvery(matchers []match.Matcher) match.Matcher {
|
func glueAsEvery(matchers []match.Matcher) match.Matcher {
|
||||||
|
@ -187,7 +192,7 @@ func glueAsEvery(matchers []match.Matcher) match.Matcher {
|
||||||
return every
|
return every
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertMatchers(matchers []match.Matcher) []match.Matcher {
|
func minimizeMatchers(matchers []match.Matcher) []match.Matcher {
|
||||||
var done match.Matcher
|
var done match.Matcher
|
||||||
var left, right, count int
|
var left, right, count int
|
||||||
|
|
||||||
|
@ -201,7 +206,6 @@ func convertMatchers(matchers []match.Matcher) []match.Matcher {
|
||||||
} else {
|
} else {
|
||||||
cl, gl := done.Len(), glued.Len()
|
cl, gl := done.Len(), glued.Len()
|
||||||
swap = cl > -1 && gl > -1 && gl > cl
|
swap = cl > -1 && gl > -1 && gl > cl
|
||||||
|
|
||||||
swap = swap || count < r-l
|
swap = swap || count < r-l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +232,7 @@ func convertMatchers(matchers []match.Matcher) []match.Matcher {
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertMatchers(next)
|
return minimizeMatchers(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileMatchers(matchers []match.Matcher) (match.Matcher, error) {
|
func compileMatchers(matchers []match.Matcher) (match.Matcher, error) {
|
||||||
|
@ -258,36 +262,29 @@ func compileMatchers(matchers []match.Matcher) (match.Matcher, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _, ok := val.(match.BTree)
|
|
||||||
// fmt.Println("a tree", ok)
|
|
||||||
|
|
||||||
left := matchers[:idx]
|
left := matchers[:idx]
|
||||||
var right []match.Matcher
|
var right []match.Matcher
|
||||||
if len(matchers) > idx+1 {
|
if len(matchers) > idx+1 {
|
||||||
right = matchers[idx+1:]
|
right = matchers[idx+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
tree := match.BTree{Value: val}
|
var l, r match.Matcher
|
||||||
|
var err error
|
||||||
if len(left) > 0 {
|
if len(left) > 0 {
|
||||||
l, err := compileMatchers(left)
|
l, err = compileMatchers(left)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.Left = l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(right) > 0 {
|
if len(right) > 0 {
|
||||||
r, err := compileMatchers(right)
|
r, err = compileMatchers(right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.Right = r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree, nil
|
return match.NewBTree(val, l, r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func do(node node, s string) (m match.Matcher, err error) {
|
func do(node node, s string) (m match.Matcher, err error) {
|
||||||
|
@ -306,7 +303,7 @@ func do(node node, s string) (m match.Matcher, err error) {
|
||||||
if _, ok := node.(*nodeAnyOf); ok {
|
if _, ok := node.(*nodeAnyOf); ok {
|
||||||
m = match.AnyOf{matchers}
|
m = match.AnyOf{matchers}
|
||||||
} else {
|
} else {
|
||||||
m, err = compileMatchers(convertMatchers(matchers))
|
m, err = compileMatchers(minimizeMatchers(matchers))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -328,7 +325,7 @@ func do(node node, s string) (m match.Matcher, err error) {
|
||||||
m = match.Single{s}
|
m = match.Single{s}
|
||||||
|
|
||||||
case *nodeText:
|
case *nodeText:
|
||||||
m = match.Raw{n.text}
|
m = match.NewRaw(n.text)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("could not compile tree: unknown node type")
|
return nil, fmt.Errorf("could not compile tree: unknown node type")
|
||||||
|
@ -370,7 +367,7 @@ func do2(node node, s string) ([]match.Matcher, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, matchers := range ways {
|
for _, matchers := range ways {
|
||||||
c, err := compileMatchers(convertMatchers(matchers))
|
c, err := compileMatchers(minimizeMatchers(matchers))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -404,7 +401,7 @@ func do2(node node, s string) ([]match.Matcher, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, matchers := range ways {
|
for _, matchers := range ways {
|
||||||
c, err := compileMatchers(convertMatchers(matchers))
|
c, err := compileMatchers(minimizeMatchers(matchers))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -427,7 +424,7 @@ func do2(node node, s string) ([]match.Matcher, error) {
|
||||||
result = append(result, match.Single{s})
|
result = append(result, match.Single{s})
|
||||||
|
|
||||||
case *nodeText:
|
case *nodeText:
|
||||||
result = append(result, match.Raw{n.text})
|
result = append(result, match.NewRaw(n.text))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("could not compile tree: unknown node type")
|
return nil, fmt.Errorf("could not compile tree: unknown node type")
|
||||||
|
|
189
compiler_test.go
189
compiler_test.go
|
@ -74,42 +74,47 @@ func TestCompileMatchers(t *testing.T) {
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Super{},
|
match.Super{},
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
match.Raw{"c"},
|
match.Raw{"c", 1},
|
||||||
},
|
},
|
||||||
match.BTree{
|
match.NewBTree(
|
||||||
Left: match.BTree{
|
match.Raw{"c", 1},
|
||||||
Left: match.Super{},
|
match.NewBTree(
|
||||||
Value: match.Single{separators},
|
match.Single{separators},
|
||||||
|
match.Super{},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]match.Matcher{
|
||||||
|
match.Any{},
|
||||||
|
match.Raw{"c", 1},
|
||||||
|
match.Any{},
|
||||||
|
},
|
||||||
|
match.NewBTree(
|
||||||
|
match.Raw{"c", 1},
|
||||||
|
match.Any{},
|
||||||
|
match.Any{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]match.Matcher{
|
||||||
|
match.Range{'a', 'c', true},
|
||||||
|
match.List{"zte", false},
|
||||||
|
match.Raw{"c", 1},
|
||||||
|
match.Single{},
|
||||||
|
},
|
||||||
|
match.Row{
|
||||||
|
Matchers: match.Matchers{
|
||||||
|
match.Range{'a', 'c', true},
|
||||||
|
match.List{"zte", false},
|
||||||
|
match.Raw{"c", 1},
|
||||||
|
match.Single{},
|
||||||
},
|
},
|
||||||
Value: match.Raw{"c"},
|
Length: 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
[]match.Matcher{
|
|
||||||
match.Any{},
|
|
||||||
match.Raw{"c"},
|
|
||||||
match.Any{},
|
|
||||||
},
|
|
||||||
match.BTree{
|
|
||||||
Left: match.Any{},
|
|
||||||
Value: match.Raw{"c"},
|
|
||||||
Right: match.Any{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]match.Matcher{
|
|
||||||
match.Range{'a', 'c', true},
|
|
||||||
match.List{"zte", false},
|
|
||||||
match.Raw{"c"},
|
|
||||||
match.Single{},
|
|
||||||
},
|
|
||||||
match.Row{Matchers: match.Matchers{
|
|
||||||
match.Range{'a', 'c', true},
|
|
||||||
match.List{"zte", false},
|
|
||||||
match.Raw{"c"},
|
|
||||||
match.Single{},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
} {
|
} {
|
||||||
act, err := compileMatchers(test.in)
|
act, err := compileMatchers(test.in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -132,17 +137,20 @@ func TestConvertMatchers(t *testing.T) {
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Range{'a', 'c', true},
|
match.Range{'a', 'c', true},
|
||||||
match.List{"zte", false},
|
match.List{"zte", false},
|
||||||
match.Raw{"c"},
|
match.Raw{"c", 1},
|
||||||
match.Single{},
|
match.Single{},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Row{Matchers: match.Matchers{
|
match.Row{
|
||||||
match.Range{'a', 'c', true},
|
Matchers: match.Matchers{
|
||||||
match.List{"zte", false},
|
match.Range{'a', 'c', true},
|
||||||
match.Raw{"c"},
|
match.List{"zte", false},
|
||||||
match.Single{},
|
match.Raw{"c", 1},
|
||||||
}},
|
match.Single{},
|
||||||
|
},
|
||||||
|
Length: 4,
|
||||||
|
},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -150,7 +158,7 @@ func TestConvertMatchers(t *testing.T) {
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Range{'a', 'c', true},
|
match.Range{'a', 'c', true},
|
||||||
match.List{"zte", false},
|
match.List{"zte", false},
|
||||||
match.Raw{"c"},
|
match.Raw{"c", 1},
|
||||||
match.Single{},
|
match.Single{},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
match.Single{},
|
match.Single{},
|
||||||
|
@ -158,16 +166,19 @@ func TestConvertMatchers(t *testing.T) {
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Row{Matchers: match.Matchers{
|
match.Row{
|
||||||
match.Range{'a', 'c', true},
|
Matchers: match.Matchers{
|
||||||
match.List{"zte", false},
|
match.Range{'a', 'c', true},
|
||||||
match.Raw{"c"},
|
match.List{"zte", false},
|
||||||
}},
|
match.Raw{"c", 1},
|
||||||
|
},
|
||||||
|
Length: 3,
|
||||||
|
},
|
||||||
match.Min{3},
|
match.Min{3},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
act := convertMatchers(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: %s;\nexp: %s", id, act, test.exp)
|
||||||
continue
|
continue
|
||||||
|
@ -197,7 +208,7 @@ func TestCompiler(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeText{text: "abc"}),
|
ast: pattern(&nodeText{text: "abc"}),
|
||||||
result: match.Raw{"abc"},
|
result: match.Raw{"abc", 3},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeAny{}),
|
ast: pattern(&nodeAny{}),
|
||||||
|
@ -247,25 +258,33 @@ func TestCompiler(t *testing.T) {
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}, &nodeSingle{}),
|
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}, &nodeSingle{}),
|
||||||
sep: separators,
|
sep: separators,
|
||||||
result: match.BTree{
|
result: match.NewBTree(
|
||||||
Left: match.Any{separators},
|
match.Row{
|
||||||
Value: match.Row{Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Raw{"abc"},
|
match.Raw{"abc", 3},
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
}},
|
},
|
||||||
},
|
Length: 4,
|
||||||
|
},
|
||||||
|
match.Any{separators},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSingle{}),
|
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSingle{}),
|
||||||
sep: separators,
|
sep: separators,
|
||||||
result: match.BTree{
|
result: match.NewBTree(
|
||||||
Left: match.Super{},
|
match.Row{
|
||||||
Value: match.Row{Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
match.Raw{"abc"},
|
match.Raw{"abc", 3},
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
}},
|
},
|
||||||
},
|
Length: 5,
|
||||||
|
},
|
||||||
|
match.Super{},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}),
|
ast: pattern(&nodeAny{}, &nodeText{text: "abc"}),
|
||||||
|
@ -284,29 +303,33 @@ func TestCompiler(t *testing.T) {
|
||||||
result: match.Contains{"abc", false},
|
result: match.Contains{"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.BTree{Left: match.Any{separators}, Value: match.Raw{"abc"}, Right: match.Any{separators}},
|
result: match.NewBTree(
|
||||||
|
match.Raw{"abc", 3},
|
||||||
|
match.Any{separators},
|
||||||
|
match.Any{separators},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSuper{}, &nodeSingle{}),
|
ast: pattern(&nodeSuper{}, &nodeSingle{}, &nodeText{text: "abc"}, &nodeSuper{}, &nodeSingle{}),
|
||||||
result: match.BTree{
|
result: match.NewBTree(
|
||||||
Left: match.Min{1},
|
match.Raw{"abc", 3},
|
||||||
Value: match.Raw{"abc"},
|
match.Min{1},
|
||||||
Right: match.Min{1},
|
match.Min{1},
|
||||||
},
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(anyOf(&nodeText{text: "abc"})),
|
ast: pattern(anyOf(&nodeText{text: "abc"})),
|
||||||
result: match.AnyOf{match.Matchers{
|
result: match.AnyOf{match.Matchers{
|
||||||
match.Raw{"abc"},
|
match.Raw{"abc", 3},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(anyOf(pattern(anyOf(pattern(&nodeText{text: "abc"}))))),
|
ast: pattern(anyOf(pattern(anyOf(pattern(&nodeText{text: "abc"}))))),
|
||||||
result: match.AnyOf{match.Matchers{
|
result: match.AnyOf{match.Matchers{
|
||||||
match.AnyOf{match.Matchers{
|
match.AnyOf{match.Matchers{
|
||||||
match.Raw{"abc"},
|
match.Raw{"abc", 3},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -316,13 +339,17 @@ func TestCompiler(t *testing.T) {
|
||||||
&nodeRange{lo: 'a', hi: 'x', not: true},
|
&nodeRange{lo: 'a', hi: 'x', not: true},
|
||||||
&nodeAny{},
|
&nodeAny{},
|
||||||
),
|
),
|
||||||
result: match.BTree{
|
result: match.NewBTree(
|
||||||
Value: match.Row{Matchers: match.Matchers{
|
match.Row{
|
||||||
match.Range{Lo: 'a', Hi: 'z'},
|
Matchers: match.Matchers{
|
||||||
match.Range{Lo: 'a', Hi: 'x', Not: true},
|
match.Range{Lo: 'a', Hi: 'z'},
|
||||||
}},
|
match.Range{Lo: 'a', Hi: 'x', Not: true},
|
||||||
Right: match.Super{},
|
},
|
||||||
},
|
Length: 2,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
match.Super{},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// ast: pattern(
|
// ast: pattern(
|
||||||
|
@ -330,9 +357,9 @@ 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"}}},
|
// 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{"a"}, match.Raw{"d"}}},
|
||||||
// match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"c"}}},
|
// match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"c", 1}}},
|
||||||
// match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"d"}}},
|
// match.Row{Matchers: match.Matchers{match.Raw{"b"}, match.Raw{"d"}}},
|
||||||
// }},
|
// }},
|
||||||
// },
|
// },
|
||||||
|
|
|
@ -36,7 +36,7 @@ func (self Any) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Any) Len() int {
|
func (self Any) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Any) Kind() Kind {
|
func (self Any) Kind() Kind {
|
||||||
|
|
|
@ -7,38 +7,50 @@ import (
|
||||||
|
|
||||||
type BTree struct {
|
type BTree struct {
|
||||||
Value, Left, Right Matcher
|
Value, Left, Right Matcher
|
||||||
|
VLen, LLen, RLen int
|
||||||
|
Length int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBTree(Value, Left, Right Matcher) (tree BTree) {
|
||||||
|
tree.Value = Value
|
||||||
|
tree.Left = Left
|
||||||
|
tree.Right = Right
|
||||||
|
|
||||||
|
lenOk := true
|
||||||
|
if tree.VLen = Value.Len(); tree.VLen == -1 {
|
||||||
|
lenOk = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if Left != nil {
|
||||||
|
if tree.LLen = Left.Len(); tree.LLen == -1 {
|
||||||
|
lenOk = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if Right != nil {
|
||||||
|
if tree.RLen = Right.Len(); tree.RLen == -1 {
|
||||||
|
lenOk = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if lenOk {
|
||||||
|
tree.Length = tree.LLen + tree.VLen + tree.RLen
|
||||||
|
} else {
|
||||||
|
tree.Length = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self BTree) Kind() Kind {
|
func (self BTree) Kind() Kind {
|
||||||
return KindBTree
|
return KindBTree
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self BTree) len() (l, v, r int, ok bool) {
|
|
||||||
v = self.Value.Len()
|
|
||||||
|
|
||||||
if self.Left != nil {
|
|
||||||
l = self.Left.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.Right != nil {
|
|
||||||
r = self.Right.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = l > -1 && v > -1 && r > -1
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self BTree) Len() int {
|
func (self BTree) Len() int {
|
||||||
l, v, r, ok := self.len()
|
return self.Length
|
||||||
if ok {
|
|
||||||
return l + v + r
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
// todo?
|
||||||
func (self BTree) Index(s string) (int, []int) {
|
func (self BTree) Index(s string) (int, []int) {
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
@ -46,17 +58,16 @@ func (self BTree) Index(s string) (int, []int) {
|
||||||
func (self BTree) Match(s string) bool {
|
func (self BTree) Match(s string) bool {
|
||||||
inputLen := len(s)
|
inputLen := len(s)
|
||||||
|
|
||||||
lLen, vLen, rLen, ok := self.len()
|
if self.Length != -1 && self.Length > inputLen {
|
||||||
if ok && lLen+vLen+rLen > inputLen {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset, limit int
|
var offset, limit int
|
||||||
if lLen >= 0 {
|
if self.LLen >= 0 {
|
||||||
offset = lLen
|
offset = self.LLen
|
||||||
}
|
}
|
||||||
if rLen >= 0 {
|
if self.RLen >= 0 {
|
||||||
limit = inputLen - rLen
|
limit = inputLen - self.RLen
|
||||||
} else {
|
} else {
|
||||||
limit = inputLen
|
limit = inputLen
|
||||||
}
|
}
|
||||||
|
@ -79,7 +90,7 @@ func (self BTree) Match(s string) bool {
|
||||||
for i := len(segments) - 1; i >= 0; i-- {
|
for i := len(segments) - 1; i >= 0; i-- {
|
||||||
length := segments[i]
|
length := segments[i]
|
||||||
|
|
||||||
if rLen >= 0 && inputLen-(offset+index+length) != rLen {
|
if self.RLen >= 0 && inputLen-(offset+index+length) != self.RLen {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ func (self Contains) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Contains) Len() int {
|
func (self Contains) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Contains) Kind() Kind {
|
func (self Contains) Kind() Kind {
|
||||||
|
|
|
@ -16,17 +16,12 @@ func (self List) Kind() Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self List) Match(s string) bool {
|
func (self List) Match(s string) bool {
|
||||||
if utf8.RuneCountInString(s) > 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
inList := strings.Index(self.List, s) != -1
|
inList := strings.Index(self.List, s) != -1
|
||||||
|
|
||||||
return inList == !self.Not
|
return inList == !self.Not
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self List) Len() int {
|
func (self List) Len() int {
|
||||||
return 1
|
return lenOne
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self List) Index(s string) (int, []int) {
|
func (self List) Index(s string) (int, []int) {
|
||||||
|
|
|
@ -27,6 +27,9 @@ const (
|
||||||
KindContains
|
KindContains
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const lenOne = 1
|
||||||
|
const lenNo = -1
|
||||||
|
|
||||||
type Matcher interface {
|
type Matcher interface {
|
||||||
Match(string) bool
|
Match(string) bool
|
||||||
Index(string) (int, []int)
|
Index(string) (int, []int)
|
||||||
|
|
15
match/max.go
15
match/max.go
|
@ -10,12 +10,19 @@ type Max struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Max) Match(s string) bool {
|
func (self Max) Match(s string) bool {
|
||||||
return utf8.RuneCountInString(s) <= self.Limit
|
var l int
|
||||||
|
for range s {
|
||||||
|
l += 1
|
||||||
|
if l > self.Limit {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Max) Index(s string) (int, []int) {
|
func (self Max) Index(s string) (int, []int) {
|
||||||
c := utf8.RuneCountInString(s)
|
if !self.Match(s) {
|
||||||
if c < self.Limit {
|
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +41,7 @@ func (self Max) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Max) Len() int {
|
func (self Max) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Max) Search(s string) (int, int, bool) {
|
func (self Max) Search(s string) (int, int, bool) {
|
||||||
|
|
12
match/min.go
12
match/min.go
|
@ -10,7 +10,15 @@ type Min struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Min) Match(s string) bool {
|
func (self Min) Match(s string) bool {
|
||||||
return utf8.RuneCountInString(s) >= self.Limit
|
var l int
|
||||||
|
for range s {
|
||||||
|
l += 1
|
||||||
|
if l >= self.Limit {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Min) Index(s string) (int, []int) {
|
func (self Min) Index(s string) (int, []int) {
|
||||||
|
@ -33,7 +41,7 @@ func (self Min) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Min) Len() int {
|
func (self Min) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Min) Search(s string) (int, int, bool) {
|
func (self Min) Search(s string) (int, int, bool) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (self Prefix) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Prefix) Len() int {
|
func (self Prefix) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Prefix) Search(s string) (i int, l int, ok bool) {
|
func (self Prefix) Search(s string) (i int, l int, ok bool) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (self PrefixSuffix) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self PrefixSuffix) Len() int {
|
func (self PrefixSuffix) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self PrefixSuffix) Search(s string) (i int, l int, ok bool) {
|
func (self PrefixSuffix) Search(s string) (i int, l int, ok bool) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ func (self Range) Kind() Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Range) Len() int {
|
func (self Range) Len() int {
|
||||||
return 1
|
return lenOne
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Range) Match(s string) bool {
|
func (self Range) Match(s string) bool {
|
||||||
|
|
15
match/raw.go
15
match/raw.go
|
@ -3,11 +3,20 @@ package match
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// raw represents raw string to match
|
// raw represents raw string to match
|
||||||
type Raw struct {
|
type Raw struct {
|
||||||
Str string
|
Str string
|
||||||
|
Length int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRaw(s string) Raw {
|
||||||
|
return Raw{
|
||||||
|
Str: s,
|
||||||
|
Length: utf8.RuneCountInString(s),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Raw) Match(s string) bool {
|
func (self Raw) Match(s string) bool {
|
||||||
|
@ -15,7 +24,7 @@ func (self Raw) Match(s string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Raw) Len() int {
|
func (self Raw) Len() int {
|
||||||
return len(self.Str)
|
return self.Length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Raw) Kind() Kind {
|
func (self Raw) Kind() Kind {
|
||||||
|
@ -28,7 +37,7 @@ func (self Raw) Index(s string) (index int, segments []int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
segments = []int{len(self.Str)}
|
segments = []int{self.Length}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
48
match/row.go
48
match/row.go
|
@ -2,27 +2,15 @@ package match
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Row struct {
|
type Row struct {
|
||||||
Matchers Matchers
|
Matchers Matchers
|
||||||
len int
|
Length int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Row) Add(m Matcher) error {
|
func (self Row) matchAll(s string) bool {
|
||||||
if l := m.Len(); l == -1 {
|
|
||||||
return fmt.Errorf("matcher should have fixed length")
|
|
||||||
}
|
|
||||||
|
|
||||||
self.Matchers = append(self.Matchers, m)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Row) Match(s string) bool {
|
|
||||||
if len(s) < self.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var idx int
|
var idx int
|
||||||
for _, m := range self.Matchers {
|
for _, m := range self.Matchers {
|
||||||
l := m.Len()
|
l := m.Len()
|
||||||
|
@ -36,21 +24,33 @@ func (self Row) Match(s string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) Len() (l int) {
|
func (self Row) Match(s string) bool {
|
||||||
if self.len == 0 {
|
if utf8.RuneCountInString(s) < self.Length {
|
||||||
for _, m := range self.Matchers {
|
return false
|
||||||
self.len += m.Len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.len
|
return self.matchAll(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Row) Len() (l int) {
|
||||||
|
return self.Length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) Index(s string) (int, []int) {
|
func (self Row) Index(s string) (int, []int) {
|
||||||
|
l := utf8.RuneCountInString(s)
|
||||||
|
if l < self.Length {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
for i := range s {
|
for i := range s {
|
||||||
sub := s[i:]
|
sub := s[i:]
|
||||||
if self.Match(sub) {
|
if self.matchAll(sub) {
|
||||||
return i, []int{self.Len()}
|
return i, []int{self.Length}
|
||||||
|
}
|
||||||
|
|
||||||
|
l -= 1
|
||||||
|
if l < self.Length {
|
||||||
|
return -1, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,5 +62,5 @@ func (self Row) Kind() Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) String() string {
|
func (self Row) String() string {
|
||||||
return fmt.Sprintf("<row:[%s]>", self.Matchers)
|
return fmt.Sprintf("<row_%d:[%s]>", self.Length, self.Matchers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,11 @@ type Single struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Single) Match(s string) bool {
|
func (self Single) Match(s string) bool {
|
||||||
return utf8.RuneCountInString(s) == 1 && strings.IndexAny(s, self.Separators) == -1
|
return strings.IndexAny(s, self.Separators) == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Single) Len() int {
|
func (self Single) Len() int {
|
||||||
return 1
|
return lenOne
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Single) Index(s string) (int, []int) {
|
func (self Single) Index(s string) (int, []int) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ func (self Suffix) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Suffix) Len() int {
|
func (self Suffix) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Suffix) Search(s string) (i int, l int, ok bool) {
|
func (self Suffix) Search(s string) (i int, l int, ok bool) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ func (self Super) Match(s string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Super) Len() int {
|
func (self Super) Len() int {
|
||||||
return -1
|
return lenNo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Super) Index(s string) (int, []int) {
|
func (self Super) Index(s string) (int, []int) {
|
||||||
|
|
Loading…
Reference in New Issue