浏览代码

fix #1003

tags/v2.1.0-rc1
Shivaram Lingamneni 4 年前
父节点
当前提交
be0dedf260

+ 19
- 27
irc/client_lookup_set.go 查看文件

@@ -7,14 +7,12 @@ package irc
7 7
 import (
8 8
 	"regexp"
9 9
 	"strings"
10
+	"sync"
10 11
 	"time"
11 12
 
12
-	"github.com/goshuirc/irc-go/ircmatch"
13
-
14 13
 	"github.com/oragono/oragono/irc/caps"
15 14
 	"github.com/oragono/oragono/irc/modes"
16
-
17
-	"sync"
15
+	"github.com/oragono/oragono/irc/utils"
18 16
 )
19 17
 
20 18
 // ClientManager keeps track of clients by nick, enforcing uniqueness of casefolded nicks
@@ -301,12 +299,16 @@ func (clients *ClientManager) FindAll(userhost string) (set ClientSet) {
301 299
 	if err != nil {
302 300
 		return set
303 301
 	}
304
-	matcher := ircmatch.MakeMatch(userhost)
302
+	matcher, err := utils.CompileGlob(userhost, false)
303
+	if err != nil {
304
+		// not much we can do here
305
+		return
306
+	}
305 307
 
306 308
 	clients.RLock()
307 309
 	defer clients.RUnlock()
308 310
 	for _, client := range clients.byNick {
309
-		if matcher.Match(client.NickMaskCasefolded()) {
311
+		if matcher.MatchString(client.NickMaskCasefolded()) {
310 312
 			set.Add(client)
311 313
 		}
312 314
 	}
@@ -330,8 +332,9 @@ type MaskInfo struct {
330 332
 // UserMaskSet holds a set of client masks and lets you match  hostnames to them.
331 333
 type UserMaskSet struct {
332 334
 	sync.RWMutex
333
-	masks  map[string]MaskInfo
334
-	regexp *regexp.Regexp
335
+	serialCacheUpdateMutex sync.Mutex
336
+	masks                  map[string]MaskInfo
337
+	regexp                 *regexp.Regexp
335 338
 }
336 339
 
337 340
 func NewUserMaskSet() *UserMaskSet {
@@ -345,6 +348,9 @@ func (set *UserMaskSet) Add(mask, creatorNickmask, creatorAccount string) (maskA
345 348
 		return
346 349
 	}
347 350
 
351
+	set.serialCacheUpdateMutex.Lock()
352
+	defer set.serialCacheUpdateMutex.Unlock()
353
+
348 354
 	set.Lock()
349 355
 	if set.masks == nil {
350 356
 		set.masks = make(map[string]MaskInfo)
@@ -373,6 +379,9 @@ func (set *UserMaskSet) Remove(mask string) (maskRemoved string, err error) {
373 379
 		return
374 380
 	}
375 381
 
382
+	set.serialCacheUpdateMutex.Lock()
383
+	defer set.serialCacheUpdateMutex.Unlock()
384
+
376 385
 	set.Lock()
377 386
 	_, removed := set.masks[mask]
378 387
 	if removed {
@@ -430,31 +439,14 @@ func (set *UserMaskSet) Length() int {
430 439
 // parts are re-joined and finally all masks are joined into a big
431 440
 // or-expression.
432 441
 func (set *UserMaskSet) setRegexp() {
433
-	var re *regexp.Regexp
434
-
435 442
 	set.RLock()
436 443
 	maskExprs := make([]string, len(set.masks))
437
-	index := 0
438 444
 	for mask := range set.masks {
439
-		manyParts := strings.Split(mask, "*")
440
-		manyExprs := make([]string, len(manyParts))
441
-		for mindex, manyPart := range manyParts {
442
-			oneParts := strings.Split(manyPart, "?")
443
-			oneExprs := make([]string, len(oneParts))
444
-			for oindex, onePart := range oneParts {
445
-				oneExprs[oindex] = regexp.QuoteMeta(onePart)
446
-			}
447
-			manyExprs[mindex] = strings.Join(oneExprs, ".")
448
-		}
449
-		maskExprs[index] = strings.Join(manyExprs, ".*")
450
-		index++
445
+		maskExprs = append(maskExprs, mask)
451 446
 	}
452 447
 	set.RUnlock()
453 448
 
454
-	if index > 0 {
455
-		expr := "^(" + strings.Join(maskExprs, "|") + ")$"
456
-		re, _ = regexp.Compile(expr)
457
-	}
449
+	re, _ := utils.CompileMasks(maskExprs)
458 450
 
459 451
 	set.Lock()
460 452
 	set.regexp = re

+ 3
- 3
irc/config.go 查看文件

@@ -853,7 +853,7 @@ func LoadConfig(filename string) (config *Config, err error) {
853 853
 	}
854 854
 
855 855
 	for _, glob := range config.Server.WebSockets.AllowedOrigins {
856
-		globre, err := utils.CompileGlob(glob)
856
+		globre, err := utils.CompileGlob(glob, false)
857 857
 		if err != nil {
858 858
 			return nil, fmt.Errorf("invalid websocket allowed-origin expression: %s", glob)
859 859
 		}
@@ -1219,7 +1219,7 @@ func compileGuestRegexp(guestFormat string, casemapping Casemapping) (standard,
1219 1219
 		return
1220 1220
 	}
1221 1221
 
1222
-	standard, err = utils.CompileGlob(guestFormat)
1222
+	standard, err = utils.CompileGlob(guestFormat, true)
1223 1223
 	if err != nil {
1224 1224
 		return
1225 1225
 	}
@@ -1235,6 +1235,6 @@ func compileGuestRegexp(guestFormat string, casemapping Casemapping) (standard,
1235 1235
 	if err != nil {
1236 1236
 		return
1237 1237
 	}
1238
-	folded, err = utils.CompileGlob(fmt.Sprintf("%s*%s", initialFolded, finalFolded))
1238
+	folded, err = utils.CompileGlob(fmt.Sprintf("%s*%s", initialFolded, finalFolded), false)
1239 1239
 	return
1240 1240
 }

+ 7
- 4
irc/handlers.go 查看文件

@@ -21,7 +21,6 @@ import (
21 21
 	"time"
22 22
 
23 23
 	"github.com/goshuirc/irc-go/ircfmt"
24
-	"github.com/goshuirc/irc-go/ircmatch"
25 24
 	"github.com/goshuirc/irc-go/ircmsg"
26 25
 	"github.com/oragono/oragono/irc/caps"
27 26
 	"github.com/oragono/oragono/irc/custime"
@@ -1280,10 +1279,14 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
1280 1279
 		return false
1281 1280
 	}
1282 1281
 
1283
-	matcher := ircmatch.MakeMatch(mask)
1282
+	matcher, err := utils.CompileGlob(mask, false)
1283
+	if err != nil {
1284
+		rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("Erroneous nickname"))
1285
+		return false
1286
+	}
1284 1287
 
1285 1288
 	for _, clientMask := range client.AllNickmasks() {
1286
-		if !klineMyself && matcher.Match(clientMask) {
1289
+		if !klineMyself && matcher.MatchString(clientMask) {
1287 1290
 			rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("This ban matches you. To KLINE yourself, you must use the command:  /KLINE MYSELF <arguments>"))
1288 1291
 			return false
1289 1292
 		}
@@ -1327,7 +1330,7 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
1327 1330
 
1328 1331
 		for _, mcl := range server.clients.AllClients() {
1329 1332
 			for _, clientMask := range mcl.AllNickmasks() {
1330
-				if matcher.Match(clientMask) {
1333
+				if matcher.MatchString(clientMask) {
1331 1334
 					clientsToKill = append(clientsToKill, mcl)
1332 1335
 					killedClientNicks = append(killedClientNicks, mcl.nick)
1333 1336
 				}

+ 11
- 4
irc/kline.go 查看文件

@@ -6,12 +6,14 @@ package irc
6 6
 import (
7 7
 	"encoding/json"
8 8
 	"fmt"
9
+	"regexp"
9 10
 	"strings"
10 11
 	"sync"
11 12
 	"time"
12 13
 
13
-	"github.com/goshuirc/irc-go/ircmatch"
14 14
 	"github.com/tidwall/buntdb"
15
+
16
+	"github.com/oragono/oragono/irc/utils"
15 17
 )
16 18
 
17 19
 const (
@@ -23,7 +25,7 @@ type KLineInfo struct {
23 25
 	// Mask that is blocked.
24 26
 	Mask string
25 27
 	// Matcher, to facilitate fast matching.
26
-	Matcher ircmatch.Matcher
28
+	Matcher *regexp.Regexp
27 29
 	// Info contains information on the ban.
28 30
 	Info IPBanInfo
29 31
 }
@@ -80,9 +82,14 @@ func (km *KLineManager) AddMask(mask string, duration time.Duration, reason, ope
80 82
 }
81 83
 
82 84
 func (km *KLineManager) addMaskInternal(mask string, info IPBanInfo) {
85
+	re, err := utils.CompileGlob(mask, false)
86
+	// this is validated externally and shouldn't fail regardless
87
+	if err != nil {
88
+		return
89
+	}
83 90
 	kln := KLineInfo{
84 91
 		Mask:    mask,
85
-		Matcher: ircmatch.MakeMatch(mask),
92
+		Matcher: re,
86 93
 		Info:    info,
87 94
 	}
88 95
 
@@ -189,7 +196,7 @@ func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info IPBanIn
189 196
 
190 197
 	for _, entryInfo := range km.entries {
191 198
 		for _, mask := range masks {
192
-			if entryInfo.Matcher.Match(mask) {
199
+			if entryInfo.Matcher.MatchString(mask) {
193 200
 				return true, entryInfo.Info
194 201
 			}
195 202
 		}

+ 38
- 6
irc/utils/glob.go 查看文件

@@ -11,21 +11,53 @@ import (
11 11
 
12 12
 // yet another glob implementation in Go
13 13
 
14
-func CompileGlob(glob string) (result *regexp.Regexp, err error) {
15
-	var buf bytes.Buffer
16
-	buf.WriteByte('^')
14
+func addRegexp(buf *bytes.Buffer, glob string, submatch bool) (err error) {
17 15
 	for _, r := range glob {
18 16
 		switch r {
19 17
 		case '*':
20
-			buf.WriteString("(.*)")
18
+			if submatch {
19
+				buf.WriteString("(.*)")
20
+			} else {
21
+				buf.WriteString(".*")
22
+			}
21 23
 		case '?':
22
-			buf.WriteString("(.)")
24
+			if submatch {
25
+				buf.WriteString("(.)")
26
+			} else {
27
+				buf.WriteString(".")
28
+			}
23 29
 		case 0xFFFD:
24
-			return nil, &syntax.Error{Code: syntax.ErrInvalidUTF8, Expr: glob}
30
+			return &syntax.Error{Code: syntax.ErrInvalidUTF8, Expr: glob}
25 31
 		default:
26 32
 			buf.WriteString(regexp.QuoteMeta(string(r)))
27 33
 		}
28 34
 	}
35
+	return
36
+}
37
+
38
+func CompileGlob(glob string, submatch bool) (result *regexp.Regexp, err error) {
39
+	var buf bytes.Buffer
40
+	buf.WriteByte('^')
41
+	err = addRegexp(&buf, glob, submatch)
42
+	if err != nil {
43
+		return
44
+	}
29 45
 	buf.WriteByte('$')
30 46
 	return regexp.Compile(buf.String())
31 47
 }
48
+
49
+func CompileMasks(masks []string) (result *regexp.Regexp, err error) {
50
+	var buf bytes.Buffer
51
+	buf.WriteString("^(")
52
+	for i, mask := range masks {
53
+		err = addRegexp(&buf, mask, false)
54
+		if err != nil {
55
+			return
56
+		}
57
+		if i != len(masks)-1 {
58
+			buf.WriteByte('|')
59
+		}
60
+	}
61
+	buf.WriteString(")$")
62
+	return regexp.Compile(buf.String())
63
+}

+ 121
- 1
irc/utils/glob_test.go 查看文件

@@ -9,7 +9,7 @@ import (
9 9
 )
10 10
 
11 11
 func globMustCompile(glob string) *regexp.Regexp {
12
-	re, err := CompileGlob(glob)
12
+	re, err := CompileGlob(glob, false)
13 13
 	if err != nil {
14 14
 		panic(err)
15 15
 	}
@@ -46,3 +46,123 @@ func TestGlob(t *testing.T) {
46 46
 	assertMatches("S*e", "Skåne", true, t)
47 47
 	assertMatches("Sk?ne", "Skåne", true, t)
48 48
 }
49
+
50
+func BenchmarkGlob(b *testing.B) {
51
+	g := globMustCompile("https://*google.com")
52
+	b.ResetTimer()
53
+	for i := 0; i < b.N; i++ {
54
+		g.MatchString("https://www.google.com")
55
+	}
56
+}
57
+
58
+func BenchmarkGlobCompilation(b *testing.B) {
59
+	for i := 0; i < b.N; i++ {
60
+		CompileGlob("https://*google.com", false)
61
+	}
62
+}
63
+
64
+// these are actual bans from my production network :-/
65
+var bans = []string{
66
+	"*!*@tor-network.onion",
67
+	"`!*@*",
68
+	"qanon!*@*",
69
+	"*!bibi@tor-network.onion",
70
+	"shivarm!*@*",
71
+	"8====d!*@*",
72
+	"shiviram!*@*",
73
+	"poop*!*@*",
74
+	"shivoram!*@*",
75
+	"shivvy!*@*",
76
+	"shavirim!*@*",
77
+	"shivarm_!*@*",
78
+	"_!*@*",
79
+}
80
+
81
+func TestMasks(t *testing.T) {
82
+	matcher, err := CompileMasks(bans)
83
+	if err != nil {
84
+		panic(err)
85
+	}
86
+
87
+	if !matcher.MatchString("evan!user@tor-network.onion") {
88
+		t.Errorf("match expected")
89
+	}
90
+	if !matcher.MatchString("`!evan@b9un4fv3he44q.example.com") {
91
+		t.Errorf("match expected")
92
+	}
93
+	if matcher.MatchString("horse!horse@t5dwi8vacg47y.example.com") {
94
+		t.Errorf("match not expected")
95
+	}
96
+	if matcher.MatchString("horse_!horse@t5dwi8vacg47y.example.com") {
97
+		t.Errorf("match not expected")
98
+	}
99
+	if matcher.MatchString("shivaram!shivaram@yrqgsrjy2p7my.example.com") {
100
+		t.Errorf("match not expected")
101
+	}
102
+}
103
+
104
+func BenchmarkMasksCompile(b *testing.B) {
105
+	for i := 0; i < b.N; i++ {
106
+		CompileMasks(bans)
107
+	}
108
+}
109
+
110
+func BenchmarkMasksMatch(b *testing.B) {
111
+	matcher, _ := CompileMasks(bans)
112
+
113
+	b.ResetTimer()
114
+	for i := 0; i < b.N; i++ {
115
+		matcher.MatchString("evan!user@tor-network.onion")
116
+		matcher.MatchString("horse_!horse@t5dwi8vacg47y.example.com")
117
+		matcher.MatchString("shivaram!shivaram@yrqgsrjy2p7my.example.com")
118
+	}
119
+}
120
+
121
+// compare performance to compilation of the | clauses as separate regexes
122
+// first for compilation, then for matching
123
+
124
+func compileAll(masks []string) (result []*regexp.Regexp, err error) {
125
+	a := make([]*regexp.Regexp, 0, len(masks))
126
+	for _, mask := range masks {
127
+		m, err := CompileGlob(mask, false)
128
+		if err != nil {
129
+			return nil, err
130
+		}
131
+		a = append(a, m)
132
+	}
133
+	return a, nil
134
+}
135
+
136
+func matchesAny(masks []*regexp.Regexp, str string) bool {
137
+	for _, r := range masks {
138
+		if r.MatchString(str) {
139
+			return true
140
+		}
141
+	}
142
+	return false
143
+}
144
+
145
+func BenchmarkLinearCompile(b *testing.B) {
146
+	for i := 0; i < b.N; i++ {
147
+		compileAll(bans)
148
+	}
149
+}
150
+
151
+func BenchmarkLinearMatch(b *testing.B) {
152
+	a, err := compileAll(bans)
153
+	if err != nil {
154
+		panic(err)
155
+	}
156
+	if matchesAny(a, "horse_!horse@t5dwi8vacg47y.example.com") {
157
+		panic("incorrect match")
158
+	}
159
+	if !matchesAny(a, "evan!user@tor-network.onion") {
160
+		panic("incorrect match")
161
+	}
162
+	b.ResetTimer()
163
+	for i := 0; i < b.N; i++ {
164
+		matchesAny(a, "horse_!horse@t5dwi8vacg47y.example.com")
165
+		matchesAny(a, "evan!user@tor-network.onion")
166
+		matchesAny(a, "shivaram!shivaram@yrqgsrjy2p7my.example.com")
167
+	}
168
+}

+ 0
- 19
vendor/github.com/goshuirc/e-nfa/.travis.yml 查看文件

@@ -1,19 +0,0 @@
1
-language: go
2
-
3
-go:
4
-    - 1.4
5
-    - tip
6
-
7
-before_install:
8
-    - go get golang.org/x/tools/cmd/cover
9
-    - go get golang.org/x/tools/cmd/vet
10
-    - go get golang.org/x/tools/cmd/goimports
11
-    - go get github.com/golang/lint/golint
12
-    - go get github.com/mattn/goveralls
13
-
14
-script:
15
-    - go vet ./...
16
-#    - $HOME/gopath/bin/goveralls -coverprofile=coverage.cov -service=travis-ci
17
-#    - bash <(curl -s https://codecov.io/bash)
18
-    - go test -bench=. -benchmem ./...
19
-    #- sh ./install_all_cmd.sh

+ 0
- 122
vendor/github.com/goshuirc/e-nfa/README.md 查看文件

@@ -1,122 +0,0 @@
1
-ε-NFA: Epsilon-Nondeterministic finite automaton
2
-==============
3
-
4
-[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/kkdai/e-nfa/master/LICENSE)  [![GoDoc](https://godoc.org/github.com/kkdai/e-nfa?status.svg)](https://godoc.org/github.com/kkdai/e-nfa)  [![Build Status](https://travis-ci.org/kkdai/e-nfa.svg?branch=master)](https://travis-ci.org/kkdai/e-nfa)
5
-
6
-
7
-
8
-![image](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/NFAexample.svg/250px-NFAexample.svg.png)
9
-
10
-
11
-
12
-What is Epsilon-Nondeterministic finite automaton
13
-=============
14
-
15
-`ε-NFA`: Epsilon-Nondeterministic finite automaton (so call:Nondeterministic finite automaton with ε-moves)
16
-
17
-In the automata theory, a nondeterministic finite automaton with ε-moves (NFA-ε)(also known as NFA-λ) is an extension of nondeterministic finite automaton(NFA), which allows a transformation to a new state without consuming any input symbols. The transitions without consuming an input symbol are called ε-transitions or λ-transitions. In the state diagrams, they are usually labeled with the Greek letter ε or λ.
18
-
19
-(sited from [here](https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton))
20
-
21
-
22
-Looking for DFA implement?
23
-=============
24
-
25
-I also write a DFA implenent in Go here. [https://github.com/kkdai/dfa](https://github.com/kkdai/dfa)
26
-
27
-Looking for NFA implement?
28
-=============
29
-
30
-I also write a NFA implenent in Go here. [https://github.com/kkdai/nfa](https://github.com/kkdai/nfa)
31
-
32
-
33
-Installation and Usage
34
-=============
35
-
36
-
37
-Install
38
----------------
39
-
40
-    go get github.com/kkdai/e-nfa
41
-
42
-
43
-
44
-Usage
45
----------------
46
-
47
-Following is sample code to implement a epsilon-NFA automata diagram as follow:
48
-
49
-![image](image/eNFA.png)
50
-
51
-
52
-
53
-```go
54
-
55
-package main
56
-
57
-import (
58
-    "github.com/kkdai/enfa"
59
-    "fmt"
60
-)
61
-
62
-func main() {
63
-
64
-	nfa := NewENFA(0, false)
65
-	nfa.AddState(1, false)
66
-	nfa.AddState(2, false)
67
-	nfa.AddState(3, true)
68
-	nfa.AddState(4, false)
69
-	nfa.AddState(5, false)
70
-
71
-	nfa.AddTransition(0, "1", 1)
72
-	nfa.AddTransition(0, "0", 4)
73
-
74
-	nfa.AddTransition(1, "1", 2)
75
-	nfa.AddTransition(1, "", 3) //epsilon
76
-	nfa.AddTransition(2, "1", 3)
77
-	nfa.AddTransition(4, "0", 5)
78
-	nfa.AddTransition(4, "", 1, 2) //E -> epsilon B C
79
-	nfa.AddTransition(5, "0", 3)
80
-
81
-	nfa.PrintTransitionTable()
82
-
83
-	if !nfa.VerifyInputs([]string{"1"}) {
84
-		fmt.Printf("Verify inputs is failed")
85
-	}
86
-
87
-	nfa.Reset()
88
-
89
-	if !nfa.VerifyInputs([]string{"1", "1", "1"}) {
90
-		fmt.Printf("Verify inputs is failed")
91
-	}
92
-
93
-	nfa.Reset()
94
-
95
-	if !nfa.VerifyInputs([]string{"0", "1"}) {
96
-		fmt.Printf"Verify inputs is failed")
97
-	}
98
-
99
-	nfa.Reset()
100
-	if !nfa.VerifyInputs([]string{"0", "0", "0"}) {
101
-		fmt.Printf("Verify inputs is failed")
102
-	}
103
-}
104
-
105
-```
106
-
107
-Inspired By
108
-=============
109
-
110
-- [ε-NFA: Wiki](https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton_with_%CE%B5-moves)
111
-- [Coursera: Automata](https://class.coursera.org/automata-004/)
112
-
113
-Project52
114
----------------
115
-
116
-It is one of my [project 52](https://github.com/kkdai/project52).
117
-
118
-
119
-License
120
----------------
121
-
122
-This package is licensed under MIT license. See LICENSE for details.

+ 0
- 185
vendor/github.com/goshuirc/e-nfa/enfa.go 查看文件

@@ -1,185 +0,0 @@
1
-package enfa
2
-
3
-import "fmt"
4
-
5
-type transitionInput struct {
6
-	srcState int
7
-	input    string
8
-}
9
-
10
-type destState map[int]bool
11
-
12
-type ENFA struct {
13
-	initState    int
14
-	currentState map[int]bool
15
-	totalStates  []int
16
-	finalStates  []int
17
-	transition   map[transitionInput]destState
18
-	inputMap     map[string]bool
19
-}
20
-
21
-//New a new NFA
22
-func NewENFA(initState int, isFinal bool) *ENFA {
23
-
24
-	retNFA := &ENFA{
25
-		transition: make(map[transitionInput]destState),
26
-		inputMap:   make(map[string]bool),
27
-		initState:  initState}
28
-
29
-	retNFA.currentState = make(map[int]bool)
30
-	retNFA.currentState[initState] = true
31
-	retNFA.AddState(initState, isFinal)
32
-	return retNFA
33
-}
34
-
35
-//Add new state in this NFA
36
-func (d *ENFA) AddState(state int, isFinal bool) {
37
-	if state == -1 {
38
-		fmt.Println("Cannot add state as -1, it is dead state")
39
-		return
40
-	}
41
-
42
-	d.totalStates = append(d.totalStates, state)
43
-	if isFinal {
44
-		d.finalStates = append(d.finalStates, state)
45
-	}
46
-}
47
-
48
-//Add new transition function into NFA
49
-func (d *ENFA) AddTransition(srcState int, input string, dstStateList ...int) {
50
-	find := false
51
-
52
-	//find input if exist in NFA input List
53
-	if _, ok := d.inputMap[input]; !ok {
54
-		//not exist, new input in this NFA
55
-		d.inputMap[input] = true
56
-	}
57
-
58
-	for _, v := range d.totalStates {
59
-		if v == srcState {
60
-			find = true
61
-		}
62
-	}
63
-
64
-	if !find {
65
-		fmt.Println("No such state:", srcState, " in current NFA")
66
-		return
67
-	}
68
-
69
-	dstMap := make(map[int]bool)
70
-	for _, destState := range dstStateList {
71
-		dstMap[destState] = true
72
-	}
73
-
74
-	targetTrans := transitionInput{srcState: srcState, input: input}
75
-	d.transition[targetTrans] = dstMap
76
-}
77
-
78
-func (d *ENFA) CheckPathExist(src int, input string, dst int) bool {
79
-	retMap, _ := d.transition[transitionInput{srcState: src, input: input}]
80
-	if _, ok := retMap[dst]; ok {
81
-		return true
82
-	}
83
-	return false
84
-}
85
-
86
-func (d *ENFA) Input(testInput string) []int {
87
-	updateCurrentState := make(map[int]bool)
88
-	for current, _ := range d.currentState {
89
-		for _, realTestInput := range []string{testInput, "*", "?"} {
90
-			intputTrans := transitionInput{srcState: current, input: realTestInput}
91
-			valMap, ok := d.transition[intputTrans]
92
-			if ok {
93
-				for dst, _ := range valMap {
94
-					updateCurrentState[dst] = true
95
-
96
-					//Update epsilon input way... if exist
97
-					epsilonTrans := transitionInput{srcState: dst}
98
-					if eMap, ok := d.transition[epsilonTrans]; ok {
99
-						for eDst, _ := range eMap {
100
-							updateCurrentState[eDst] = true
101
-						}
102
-					}
103
-				}
104
-			} else {
105
-				//dead state, remove in current state
106
-				//do nothing.
107
-			}
108
-		}
109
-	}
110
-
111
-	//update curret state
112
-	d.currentState = updateCurrentState
113
-
114
-	//return result
115
-	var ret []int
116
-	for state, _ := range updateCurrentState {
117
-		ret = append(ret, state)
118
-	}
119
-	return ret
120
-}
121
-
122
-//To verify current state if it is final state
123
-func (d *ENFA) Verify() bool {
124
-	for _, val := range d.finalStates {
125
-		for cState, _ := range d.currentState {
126
-			if val == cState {
127
-				return true
128
-			}
129
-		}
130
-	}
131
-	return false
132
-}
133
-
134
-//Reset NFA state to initilize state, but all state and transition function will remain
135
-func (d *ENFA) Reset() {
136
-	initState := make(map[int]bool)
137
-	initState[d.initState] = true
138
-	d.currentState = initState
139
-}
140
-
141
-//Verify if list of input could be accept by NFA or not
142
-func (d *ENFA) VerifyInputs(inputs []string) bool {
143
-	for _, v := range inputs {
144
-		d.Input(v)
145
-	}
146
-	return d.Verify()
147
-}
148
-
149
-//To print detail transition table contain of current NFA
150
-func (d *ENFA) PrintTransitionTable() {
151
-	fmt.Println("===================================================")
152
-	//list all inputs
153
-	var inputList []string
154
-	for key, _ := range d.inputMap {
155
-		if key == "" {
156
-			fmt.Printf("\tε|")
157
-		} else {
158
-			fmt.Printf("\t%s|", key)
159
-		}
160
-		inputList = append(inputList, key)
161
-	}
162
-
163
-	fmt.Printf("\n")
164
-	fmt.Println("---------------------------------------------------")
165
-
166
-	for _, state := range d.totalStates {
167
-		fmt.Printf("%d |", state)
168
-		for _, key := range inputList {
169
-			checkInput := transitionInput{srcState: state, input: key}
170
-			if dstState, ok := d.transition[checkInput]; ok {
171
-				fmt.Printf("\t")
172
-				for val, _ := range dstState {
173
-					fmt.Printf("%d,", val)
174
-				}
175
-				fmt.Printf("|")
176
-			} else {
177
-				fmt.Printf("\tNA|")
178
-			}
179
-		}
180
-		fmt.Printf("\n")
181
-	}
182
-
183
-	fmt.Println("---------------------------------------------------")
184
-	fmt.Println("===================================================")
185
-}

+ 0
- 7
vendor/github.com/goshuirc/irc-go/ircmatch/doc.go 查看文件

@@ -1,7 +0,0 @@
1
-// written by Daniel Oaks <daniel@danieloaks.net>
2
-// released under the ISC license
3
-
4
-/*
5
-Package ircmatch handles matching IRC strings with the traditional glob-like syntax.
6
-*/
7
-package ircmatch

+ 0
- 57
vendor/github.com/goshuirc/irc-go/ircmatch/ircmatch.go 查看文件

@@ -1,57 +0,0 @@
1
-package ircmatch
2
-
3
-import enfa "github.com/goshuirc/e-nfa"
4
-
5
-// Matcher represents an object that can match IRC strings.
6
-type Matcher struct {
7
-	internalENFA *enfa.ENFA
8
-}
9
-
10
-// MakeMatch creates a Matcher.
11
-func MakeMatch(globTemplate string) Matcher {
12
-	var newmatch Matcher
13
-
14
-	// assemble internal enfa
15
-	newmatch.internalENFA = enfa.NewENFA(0, false)
16
-
17
-	var currentState int
18
-	var lastWasStar bool
19
-	for _, char := range globTemplate {
20
-		if char == '*' {
21
-			if lastWasStar {
22
-				continue
23
-			}
24
-			newmatch.internalENFA.AddTransition(currentState, "*", currentState)
25
-			lastWasStar = true
26
-			continue
27
-		} else if char == '?' {
28
-			newmatch.internalENFA.AddState(currentState+1, false)
29
-			newmatch.internalENFA.AddTransition(currentState, "?", currentState+1)
30
-			currentState++
31
-		} else {
32
-			newmatch.internalENFA.AddState(currentState+1, false)
33
-			newmatch.internalENFA.AddTransition(currentState, string(char), currentState+1)
34
-			currentState++
35
-		}
36
-
37
-		lastWasStar = false
38
-	}
39
-
40
-	// create end state
41
-	newmatch.internalENFA.AddState(currentState+1, true)
42
-	newmatch.internalENFA.AddTransition(currentState, "", currentState+1)
43
-
44
-	return newmatch
45
-}
46
-
47
-// Match returns true if the given string matches this glob.
48
-func (menfa *Matcher) Match(search string) bool {
49
-	var searchChars []string
50
-	for _, char := range search {
51
-		searchChars = append(searchChars, string(char))
52
-	}
53
-
54
-	isMatch := menfa.internalENFA.VerifyInputs(searchChars)
55
-	menfa.internalENFA.Reset()
56
-	return isMatch
57
-}

+ 0
- 2
vendor/modules.txt 查看文件

@@ -17,11 +17,9 @@ github.com/go-sql-driver/mysql
17 17
 github.com/gorilla/websocket
18 18
 # github.com/goshuirc/e-nfa v0.0.0-20160917075329-7071788e3940
19 19
 ## explicit
20
-github.com/goshuirc/e-nfa
21 20
 # github.com/goshuirc/irc-go v0.0.0-20200311142257-57fd157327ac
22 21
 ## explicit
23 22
 github.com/goshuirc/irc-go/ircfmt
24
-github.com/goshuirc/irc-go/ircmatch
25 23
 github.com/goshuirc/irc-go/ircmsg
26 24
 # github.com/onsi/ginkgo v1.12.0
27 25
 ## explicit

正在加载...
取消
保存