forked from mirror/glob
Tune, new feature test
This commit is contained in:
parent
c65eb46cf3
commit
d2a191e0f0
|
@ -2,4 +2,7 @@ glob.iml
|
||||||
.idea
|
.idea
|
||||||
*.cpu
|
*.cpu
|
||||||
*.mem
|
*.mem
|
||||||
*.test
|
*.test
|
||||||
|
*.dot
|
||||||
|
*.png
|
||||||
|
*.svg
|
||||||
|
|
|
@ -3,7 +3,7 @@ sudo: false
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.5.1
|
- 1.5.3
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go test -v ./...
|
- go test -v ./...
|
||||||
|
|
|
@ -17,7 +17,7 @@ func optimize(matcher match.Matcher) match.Matcher {
|
||||||
m.Left = optimize(m.Left)
|
m.Left = optimize(m.Left)
|
||||||
m.Right = optimize(m.Right)
|
m.Right = optimize(m.Right)
|
||||||
|
|
||||||
r, ok := m.Value.(match.Raw)
|
r, ok := m.Value.(match.Text)
|
||||||
if !ok {
|
if !ok {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
@ -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.NewRaw(r.Str)
|
return match.NewText(r.Str)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, leftSuper := m.Left.(match.Super)
|
_, leftSuper := m.Left.(match.Super)
|
||||||
|
@ -325,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.NewRaw(n.text)
|
m = match.NewText(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")
|
||||||
|
@ -424,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.NewRaw(n.text))
|
result = append(result, match.NewText(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")
|
||||||
|
|
|
@ -74,10 +74,10 @@ func TestCompileMatchers(t *testing.T) {
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Super{},
|
match.Super{},
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
},
|
},
|
||||||
match.NewBTree(
|
match.NewBTree(
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
match.NewBTree(
|
match.NewBTree(
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
match.Super{},
|
match.Super{},
|
||||||
|
@ -89,11 +89,11 @@ func TestCompileMatchers(t *testing.T) {
|
||||||
{
|
{
|
||||||
[]match.Matcher{
|
[]match.Matcher{
|
||||||
match.Any{},
|
match.Any{},
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
match.NewBTree(
|
match.NewBTree(
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
match.Any{},
|
match.Any{},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
),
|
),
|
||||||
|
@ -102,17 +102,17 @@ func TestCompileMatchers(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", 1},
|
match.NewText("c"),
|
||||||
match.Single{},
|
match.Single{},
|
||||||
},
|
},
|
||||||
match.Row{
|
match.Row{
|
||||||
Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Range{'a', 'c', true},
|
match.Range{'a', 'c', true},
|
||||||
match.List{"zte", false},
|
match.List{"zte", false},
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
match.Single{},
|
match.Single{},
|
||||||
},
|
},
|
||||||
Length: 4,
|
RunesLength: 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
@ -137,7 +137,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", 1},
|
match.NewText("c"),
|
||||||
match.Single{},
|
match.Single{},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
|
@ -146,10 +146,10 @@ func TestConvertMatchers(t *testing.T) {
|
||||||
Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Range{'a', 'c', true},
|
match.Range{'a', 'c', true},
|
||||||
match.List{"zte", false},
|
match.List{"zte", false},
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
match.Single{},
|
match.Single{},
|
||||||
},
|
},
|
||||||
Length: 4,
|
RunesLength: 4,
|
||||||
},
|
},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
},
|
},
|
||||||
|
@ -158,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", 1},
|
match.NewText("c"),
|
||||||
match.Single{},
|
match.Single{},
|
||||||
match.Any{},
|
match.Any{},
|
||||||
match.Single{},
|
match.Single{},
|
||||||
|
@ -170,9 +170,9 @@ func TestConvertMatchers(t *testing.T) {
|
||||||
Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Range{'a', 'c', true},
|
match.Range{'a', 'c', true},
|
||||||
match.List{"zte", false},
|
match.List{"zte", false},
|
||||||
match.Raw{"c", 1},
|
match.NewText("c"),
|
||||||
},
|
},
|
||||||
Length: 3,
|
RunesLength: 3,
|
||||||
},
|
},
|
||||||
match.Min{3},
|
match.Min{3},
|
||||||
},
|
},
|
||||||
|
@ -208,7 +208,7 @@ func TestCompiler(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeText{text: "abc"}),
|
ast: pattern(&nodeText{text: "abc"}),
|
||||||
result: match.Raw{"abc", 3},
|
result: match.NewText("abc"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ast: pattern(&nodeAny{}),
|
ast: pattern(&nodeAny{}),
|
||||||
|
@ -261,10 +261,10 @@ func TestCompiler(t *testing.T) {
|
||||||
result: match.NewBTree(
|
result: match.NewBTree(
|
||||||
match.Row{
|
match.Row{
|
||||||
Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Raw{"abc", 3},
|
match.NewText("abc"),
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
},
|
},
|
||||||
Length: 4,
|
RunesLength: 4,
|
||||||
},
|
},
|
||||||
match.Any{separators},
|
match.Any{separators},
|
||||||
nil,
|
nil,
|
||||||
|
@ -277,10 +277,10 @@ func TestCompiler(t *testing.T) {
|
||||||
match.Row{
|
match.Row{
|
||||||
Matchers: match.Matchers{
|
Matchers: match.Matchers{
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
match.Raw{"abc", 3},
|
match.NewText("abc"),
|
||||||
match.Single{separators},
|
match.Single{separators},
|
||||||
},
|
},
|
||||||
Length: 5,
|
RunesLength: 5,
|
||||||
},
|
},
|
||||||
match.Super{},
|
match.Super{},
|
||||||
nil,
|
nil,
|
||||||
|
@ -306,7 +306,7 @@ func TestCompiler(t *testing.T) {
|
||||||
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.Raw{"abc", 3},
|
match.NewText("abc"),
|
||||||
match.Any{separators},
|
match.Any{separators},
|
||||||
match.Any{separators},
|
match.Any{separators},
|
||||||
),
|
),
|
||||||
|
@ -314,7 +314,7 @@ func TestCompiler(t *testing.T) {
|
||||||
{
|
{
|
||||||
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.Raw{"abc", 3},
|
match.NewText("abc"),
|
||||||
match.Min{1},
|
match.Min{1},
|
||||||
match.Min{1},
|
match.Min{1},
|
||||||
),
|
),
|
||||||
|
@ -322,14 +322,14 @@ func TestCompiler(t *testing.T) {
|
||||||
{
|
{
|
||||||
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", 3},
|
match.NewText("abc"),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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", 3},
|
match.NewText("abc"),
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -345,7 +345,7 @@ func TestCompiler(t *testing.T) {
|
||||||
match.Range{Lo: 'a', Hi: 'z'},
|
match.Range{Lo: 'a', Hi: 'z'},
|
||||||
match.Range{Lo: 'a', Hi: 'x', Not: true},
|
match.Range{Lo: 'a', Hi: 'x', Not: true},
|
||||||
},
|
},
|
||||||
Length: 2,
|
RunesLength: 2,
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
match.Super{},
|
match.Super{},
|
||||||
|
|
26
glob_test.go
26
glob_test.go
|
@ -19,7 +19,7 @@ const (
|
||||||
pattern_multiple = "https://*.google.*"
|
pattern_multiple = "https://*.google.*"
|
||||||
fixture_multiple = "https://account.google.com"
|
fixture_multiple = "https://account.google.com"
|
||||||
|
|
||||||
pattern_alternatives = "{https://*.google.*,*yahoo.*}"
|
pattern_alternatives = "{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}"
|
||||||
fixture_alternatives = "http://yahoo.com"
|
fixture_alternatives = "http://yahoo.com"
|
||||||
|
|
||||||
pattern_prefix = "abc*"
|
pattern_prefix = "abc*"
|
||||||
|
@ -81,14 +81,22 @@ func TestCompilePattern(t *testing.T) {
|
||||||
sep string
|
sep string
|
||||||
exp match.Matcher
|
exp match.Matcher
|
||||||
}{
|
}{
|
||||||
// {
|
// {
|
||||||
// pattern: "left*??B*abcd*[!b]??*abc*right",
|
// pattern: "left*??B*abcd*[!b]??*abc*right",
|
||||||
// exp: match.Raw{"t"},
|
// exp: match.Raw{"t"},
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// pattern: "abc*??def",
|
// pattern: "abc*??def",
|
||||||
// exp: match.Raw{"t"},
|
// exp: match.Raw{"t"},
|
||||||
// },
|
// },
|
||||||
|
{
|
||||||
|
pattern: "{abc[abc]ghi,abc[def]ghi}",
|
||||||
|
exp: match.NewBTree(
|
||||||
|
match.AnyOf{match.Matchers{match.List{"abc", false}, match.List{"qwe", false}}},
|
||||||
|
match.NewText("abc"),
|
||||||
|
match.NewText("ghi"),
|
||||||
|
),
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
glob, err := Compile(test.pattern, test.sep)
|
glob, err := Compile(test.pattern, test.sep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -15,8 +15,8 @@ func TestAnyOfIndex(t *testing.T) {
|
||||||
{
|
{
|
||||||
Matchers{
|
Matchers{
|
||||||
Any{},
|
Any{},
|
||||||
Raw{"b"},
|
Text{"b"},
|
||||||
Raw{"c"},
|
Text{"c"},
|
||||||
},
|
},
|
||||||
"abc",
|
"abc",
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -6,9 +6,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type BTree struct {
|
type BTree struct {
|
||||||
Value, Left, Right Matcher
|
Value Matcher
|
||||||
VLen, LLen, RLen int
|
Left Matcher
|
||||||
Length int
|
Right Matcher
|
||||||
|
ValueLengthRunes int
|
||||||
|
LeftLengthRunes int
|
||||||
|
RightLengthRunes int
|
||||||
|
LengthRunes int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBTree(Value, Left, Right Matcher) (tree BTree) {
|
func NewBTree(Value, Left, Right Matcher) (tree BTree) {
|
||||||
|
@ -17,33 +21,33 @@ func NewBTree(Value, Left, Right Matcher) (tree BTree) {
|
||||||
tree.Right = Right
|
tree.Right = Right
|
||||||
|
|
||||||
lenOk := true
|
lenOk := true
|
||||||
if tree.VLen = Value.Len(); tree.VLen == -1 {
|
if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 {
|
||||||
lenOk = false
|
lenOk = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if Left != nil {
|
if Left != nil {
|
||||||
if tree.LLen = Left.Len(); tree.LLen == -1 {
|
if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 {
|
||||||
lenOk = false
|
lenOk = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Right != nil {
|
if Right != nil {
|
||||||
if tree.RLen = Right.Len(); tree.RLen == -1 {
|
if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 {
|
||||||
lenOk = false
|
lenOk = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lenOk {
|
if lenOk {
|
||||||
tree.Length = tree.LLen + tree.VLen + tree.RLen
|
tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes
|
||||||
} else {
|
} else {
|
||||||
tree.Length = -1
|
tree.LengthRunes = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree
|
return tree
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self BTree) Len() int {
|
func (self BTree) Len() int {
|
||||||
return self.Length
|
return self.LengthRunes
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo?
|
// todo?
|
||||||
|
@ -54,27 +58,33 @@ 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)
|
||||||
|
|
||||||
if self.Length != -1 && self.Length > inputLen {
|
// self.Length, self.RLen and self.LLen are values meaning the length of runes for each part
|
||||||
|
// here we manipulating byte length for better optimizations
|
||||||
|
// but these checks still works, cause minLen of 1-rune string is 1 byte.
|
||||||
|
if self.LengthRunes != -1 && self.LengthRunes > inputLen {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to cut unnecessary parts
|
||||||
|
// by knowledge of length of right and left part
|
||||||
var offset, limit int
|
var offset, limit int
|
||||||
if self.LLen >= 0 {
|
if self.LeftLengthRunes >= 0 {
|
||||||
offset = self.LLen
|
offset = self.LeftLengthRunes
|
||||||
}
|
}
|
||||||
if self.RLen >= 0 {
|
if self.RightLengthRunes >= 0 {
|
||||||
limit = inputLen - self.RLen
|
limit = inputLen - self.RightLengthRunes
|
||||||
} else {
|
} else {
|
||||||
limit = inputLen
|
limit = inputLen
|
||||||
}
|
}
|
||||||
|
|
||||||
for offset < limit {
|
for offset < limit {
|
||||||
|
// search for matching part in substring
|
||||||
index, segments := self.Value.Index(s[offset:limit])
|
index, segments := self.Value.Index(s[offset:limit])
|
||||||
if index == -1 {
|
if index == -1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
l := string(s[:offset+index])
|
l := s[:offset+index]
|
||||||
var left bool
|
var left bool
|
||||||
if self.Left != nil {
|
if self.Left != nil {
|
||||||
left = self.Left.Match(l)
|
left = self.Left.Match(l)
|
||||||
|
@ -86,12 +96,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 self.RLen >= 0 && inputLen-(offset+index+length) != self.RLen {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var right bool
|
var right bool
|
||||||
|
|
||||||
var r string
|
var r string
|
||||||
// if there is no string for the right branch
|
// if there is no string for the right branch
|
||||||
if inputLen <= offset+index+length {
|
if inputLen <= offset+index+length {
|
||||||
|
|
|
@ -11,17 +11,17 @@ func TestBTree(t *testing.T) {
|
||||||
exp bool
|
exp bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
BTree{Value: Raw{"abc"}, Left: Super{}, Right: Super{}},
|
BTree{Value: Text{"abc"}, Left: Super{}, Right: Super{}},
|
||||||
"abc",
|
"abc",
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BTree{Value: Raw{"a"}, Left: Single{}, Right: Single{}},
|
BTree{Value: Text{"a"}, Left: Single{}, Right: Single{}},
|
||||||
"aaa",
|
"aaa",
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BTree{Value: Raw{"b"}, Left: Single{}},
|
BTree{Value: Text{"b"}, Left: Single{}},
|
||||||
"bbb",
|
"bbb",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,7 @@ func TestBTree(t *testing.T) {
|
||||||
Left: Super{},
|
Left: Super{},
|
||||||
Value: Single{},
|
Value: Single{},
|
||||||
},
|
},
|
||||||
Value: Raw{"c"},
|
Value: Text{"c"},
|
||||||
},
|
},
|
||||||
"abc",
|
"abc",
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -15,8 +15,8 @@ func TestEveryOfIndex(t *testing.T) {
|
||||||
{
|
{
|
||||||
Matchers{
|
Matchers{
|
||||||
Any{},
|
Any{},
|
||||||
Raw{"b"},
|
Text{"b"},
|
||||||
Raw{"c"},
|
Text{"c"},
|
||||||
},
|
},
|
||||||
"abc",
|
"abc",
|
||||||
-1,
|
-1,
|
||||||
|
|
|
@ -12,6 +12,13 @@ type List struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self List) Match(s string) bool {
|
func (self List) Match(s string) bool {
|
||||||
|
// if s 100% have two symbols
|
||||||
|
// _, w := utf8.DecodeRuneInString(s)
|
||||||
|
// if len(s) > w {
|
||||||
|
if len(s) > 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
inList := strings.Index(self.List, s) != -1
|
inList := strings.Index(self.List, s) != -1
|
||||||
return inList == !self.Not
|
return inList == !self.Not
|
||||||
}
|
}
|
||||||
|
|
43
match/raw.go
43
match/raw.go
|
@ -1,43 +0,0 @@
|
||||||
package match
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// raw represents raw string to match
|
|
||||||
type Raw struct {
|
|
||||||
Str string
|
|
||||||
Length int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRaw(s string) Raw {
|
|
||||||
return Raw{
|
|
||||||
Str: s,
|
|
||||||
Length: utf8.RuneCountInString(s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Raw) Match(s string) bool {
|
|
||||||
return self.Str == s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Raw) Len() int {
|
|
||||||
return self.Length
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Raw) Index(s string) (index int, segments []int) {
|
|
||||||
index = strings.Index(s, self.Str)
|
|
||||||
if index == -1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
segments = []int{self.Length}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Raw) String() string {
|
|
||||||
return fmt.Sprintf("<raw:%s>", self.Str)
|
|
||||||
}
|
|
16
match/row.go
16
match/row.go
|
@ -6,8 +6,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Row struct {
|
type Row struct {
|
||||||
Matchers Matchers
|
Matchers Matchers
|
||||||
Length int
|
RunesLength int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) matchAll(s string) bool {
|
func (self Row) matchAll(s string) bool {
|
||||||
|
@ -25,7 +25,7 @@ func (self Row) matchAll(s string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) Match(s string) bool {
|
func (self Row) Match(s string) bool {
|
||||||
if utf8.RuneCountInString(s) < self.Length {
|
if utf8.RuneCountInString(s) < self.RunesLength {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,23 +33,23 @@ func (self Row) Match(s string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) Len() (l int) {
|
func (self Row) Len() (l int) {
|
||||||
return self.Length
|
return self.RunesLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) Index(s string) (int, []int) {
|
func (self Row) Index(s string) (int, []int) {
|
||||||
l := utf8.RuneCountInString(s)
|
l := utf8.RuneCountInString(s)
|
||||||
if l < self.Length {
|
if l < self.RunesLength {
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range s {
|
for i := range s {
|
||||||
sub := s[i:]
|
sub := s[i:]
|
||||||
if self.matchAll(sub) {
|
if self.matchAll(sub) {
|
||||||
return i, []int{self.Length}
|
return i, []int{self.RunesLength}
|
||||||
}
|
}
|
||||||
|
|
||||||
l -= 1
|
l -= 1
|
||||||
if l < self.Length {
|
if l < self.RunesLength {
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,5 +58,5 @@ func (self Row) Index(s string) (int, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Row) String() string {
|
func (self Row) String() string {
|
||||||
return fmt.Sprintf("<row_%d:[%s]>", self.Length, self.Matchers)
|
return fmt.Sprintf("<row_%d:[%s]>", self.RunesLength, self.Matchers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package match
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// raw represents raw string to match
|
||||||
|
type Text struct {
|
||||||
|
Str string
|
||||||
|
RunesLength int
|
||||||
|
BytesLength int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewText(s string) Text {
|
||||||
|
return Text{
|
||||||
|
Str: s,
|
||||||
|
RunesLength: utf8.RuneCountInString(s),
|
||||||
|
BytesLength: len(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Text) Match(s string) bool {
|
||||||
|
return self.Str == s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Text) Len() int {
|
||||||
|
return self.RunesLength
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Text) Index(s string) (index int, segments []int) {
|
||||||
|
index = strings.Index(s, self.Str)
|
||||||
|
if index == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
segments = []int{self.BytesLength}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Text) String() string {
|
||||||
|
return fmt.Sprintf("<text:%s>", self.Str)
|
||||||
|
}
|
Loading…
Reference in New Issue