forked from monochromegane/the_platinum_searcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fixed_grep.go
108 lines (95 loc) · 2.2 KB
/
fixed_grep.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package the_platinum_searcher
import (
"bytes"
"io"
"io/ioutil"
"log"
"os"
)
type fixedGrep struct {
lineGrep
pattern pattern
}
func (g fixedGrep) grep(path string, buf []byte) {
f, err := getFileHandler(path)
if err != nil {
log.Fatalf("open: %s\n", err)
}
defer f.Close()
if f == os.Stdin {
// TODO: File type is fixed in ASCII because it can not determine the character code.
g.grepEachLines(f, ASCII, func(b []byte) bool {
return bytes.Contains(b, g.pattern.pattern)
}, func(b []byte) int {
return bytes.Index(b, g.pattern.pattern) + 1
})
return
}
var stash []byte
identified := false
var encoding int
pattern := g.pattern.pattern
for {
c, err := f.Read(buf)
if err != nil && err != io.EOF {
log.Fatalf("read: %s\n", err)
}
if err == io.EOF {
break
}
// detect encoding.
if !identified {
limit := c
if limit > 512 {
limit = 512
}
encoding = detectEncoding(buf[:limit])
if encoding == ERROR || encoding == BINARY {
break
}
if r := newEncodeReader(bytes.NewReader(pattern), encoding); r != nil {
// encode pattern to shift-jis or euc-jp.
pattern, _ = ioutil.ReadAll(r)
}
identified = true
}
// repair first line from previous last line.
if len(stash) > 0 {
var repaired []byte
index := bytes.Index(buf[:c], newLine)
if index == -1 {
repaired = append(stash, buf[:c]...)
} else {
repaired = append(stash, buf[:index]...)
}
// grep from repaied line.
if bytes.Contains(repaired, pattern) {
// grep each lines.
g.grepEachLines(f, encoding, func(b []byte) bool {
return bytes.Contains(b, g.pattern.pattern)
}, func(b []byte) int {
return bytes.Index(b, g.pattern.pattern) + 1
})
break
}
}
// grep from buffer.
if bytes.Contains(buf[:c], pattern) {
// grep each lines.
g.grepEachLines(f, encoding, func(b []byte) bool {
return bytes.Contains(b, g.pattern.pattern)
}, func(b []byte) int {
return bytes.Index(b, g.pattern.pattern) + 1
})
break
}
// stash last line.
index := bytes.LastIndex(buf[:c], newLine)
if index == -1 {
stash = append(stash, buf[:c]...)
} else {
stash = make([]byte, c-index)
copy(stash, buf[index:c])
}
}
}