|
@ -30,9 +30,9 @@ func main() { |
|
|
|
|
|
|
|
|
// Make a channel and a thread for each CPU core
|
|
|
// Make a channel and a thread for each CPU core
|
|
|
var cores = runtime.NumCPU() |
|
|
var cores = runtime.NumCPU() |
|
|
var linechan = make(chan []byte) |
|
|
|
|
|
|
|
|
var workchannel = make(chan []byte) |
|
|
for i := 0; i < cores; i++ { |
|
|
for i := 0; i < cores; i++ { |
|
|
go scannerThread(linechan, []byte(needle), &wg) |
|
|
|
|
|
|
|
|
go scannerThread(workchannel, []byte(needle), &wg) |
|
|
wg.Add(1) |
|
|
wg.Add(1) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -54,37 +54,36 @@ func main() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
linechan <- append(buf[:nread], remainder...) |
|
|
|
|
|
|
|
|
workchannel <- append(buf[:nread], remainder...) |
|
|
|
|
|
|
|
|
if err == io.EOF { |
|
|
if err == io.EOF { |
|
|
break |
|
|
break |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
close(linechan) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
close(workchannel) |
|
|
wg.Wait() |
|
|
wg.Wait() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func scannerThread(linechannel chan []byte, needle []byte, wg *sync.WaitGroup) { |
|
|
|
|
|
var line []byte |
|
|
|
|
|
|
|
|
func scannerThread(workchannel chan []byte, needle []byte, wg *sync.WaitGroup) { |
|
|
|
|
|
var batch []byte |
|
|
var ok bool |
|
|
var ok bool |
|
|
var start, end int |
|
|
var start, end int |
|
|
var linelen int |
|
|
var linelen int |
|
|
var i int |
|
|
var i int |
|
|
defer wg.Done() |
|
|
defer wg.Done() |
|
|
for { |
|
|
for { |
|
|
line, ok = <-linechannel |
|
|
|
|
|
|
|
|
batch, ok = <-workchannel |
|
|
if !ok { |
|
|
if !ok { |
|
|
return // channel closed. we're done
|
|
|
return // channel closed. we're done
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// This loop is for every result found, when there are no more results it stops
|
|
|
// This loop is for every result found, when there are no more results it stops
|
|
|
for i = bytes.Index(line, needle); i != -1; i = bytes.Index(line, needle) { |
|
|
|
|
|
|
|
|
for i = bytes.Index(batch, needle); i != -1; i = bytes.Index(batch, needle) { |
|
|
start, end = i, i |
|
|
start, end = i, i |
|
|
// needle was found, but where?
|
|
|
// needle was found, but where?
|
|
|
for { // find the start
|
|
|
for { // find the start
|
|
|
if line[start] == lf { |
|
|
|
|
|
|
|
|
if batch[start] == lf { |
|
|
start++ // the line feed is from the previous line, so skip it
|
|
|
start++ // the line feed is from the previous line, so skip it
|
|
|
break |
|
|
break |
|
|
} else if start == 0 { |
|
|
} else if start == 0 { |
|
@ -94,18 +93,22 @@ func scannerThread(linechannel chan []byte, needle []byte, wg *sync.WaitGroup) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for { // find the end
|
|
|
for { // find the end
|
|
|
if line[end] == lf || end == linelen-1 { |
|
|
|
|
|
|
|
|
if batch[end] == lf { |
|
|
|
|
|
end++ // include the line feed in the line
|
|
|
|
|
|
// https://stackoverflow.com/questions/26857582/in-a-go-slice-why-does-slohi-end-at-element-hi-1
|
|
|
|
|
|
break |
|
|
|
|
|
} else if end == linelen { |
|
|
break |
|
|
break |
|
|
} |
|
|
} |
|
|
end++ |
|
|
end++ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
print(string(line[start:end]) + "\n") |
|
|
|
|
|
|
|
|
os.Stdout.Write(batch[start:end]) |
|
|
|
|
|
|
|
|
// Chop all of the bytes before the result off so it doesn't get
|
|
|
// Chop all of the bytes before the result off so it doesn't get
|
|
|
// searched again
|
|
|
// searched again
|
|
|
line = line[end:] |
|
|
|
|
|
linelen = len(line) |
|
|
|
|
|
|
|
|
batch = batch[end:] |
|
|
|
|
|
linelen = len(batch) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |