Logic complete
This commit is contained in:
parent
8bf0a25c88
commit
dd2748d8ae
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,6 +5,9 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
|
main
|
||||||
|
test
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
|
|||||||
BIN
cmd/wc-go/main
BIN
cmd/wc-go/main
Binary file not shown.
@ -12,38 +12,48 @@ type ComplexCount struct {
|
|||||||
MaxLineLength int64
|
MaxLineLength int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetComplexCount(chunk []byte) ComplexCount {
|
type ComplexChunk struct {
|
||||||
|
PrevRune rune
|
||||||
|
Chunk []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetComplexCount(chunk ComplexChunk) ComplexCount {
|
||||||
var count = ComplexCount{}
|
var count = ComplexCount{}
|
||||||
word := false
|
|
||||||
var lineLength int64
|
var lineLength int64
|
||||||
runes := bytes.Runes(chunk)
|
runes := bytes.Runes(chunk.Chunk)
|
||||||
|
prevRuneIsSpace := unicode.IsSpace(chunk.PrevRune)
|
||||||
|
var linepos int64
|
||||||
for _, b := range runes {
|
for _, b := range runes {
|
||||||
count.CharCount++
|
count.CharCount++
|
||||||
|
if b == '\n' || b == '\r' || b == '\f' {
|
||||||
|
if linepos > lineLength {
|
||||||
|
lineLength = linepos
|
||||||
|
}
|
||||||
|
linepos = 0
|
||||||
if b == '\n' {
|
if b == '\n' {
|
||||||
if lineLength > count.MaxLineLength {
|
|
||||||
count.MaxLineLength = lineLength
|
|
||||||
}
|
|
||||||
lineLength = 0
|
|
||||||
count.LineCount++
|
count.LineCount++
|
||||||
if word {
|
|
||||||
word = false
|
|
||||||
count.WordCount++
|
|
||||||
}
|
}
|
||||||
} else if unicode.IsSpace(b) {
|
|
||||||
lineLength++
|
|
||||||
if word {
|
|
||||||
word = false
|
|
||||||
count.WordCount++
|
|
||||||
}
|
}
|
||||||
|
if unicode.IsSpace(b) {
|
||||||
|
if b == '\t' {
|
||||||
|
linepos += 8 - (linepos % 8)
|
||||||
|
} else if b != '\n' && b != '\r' && b != '\f' && b != '\v' {
|
||||||
|
linepos++
|
||||||
|
}
|
||||||
|
prevRuneIsSpace = true
|
||||||
} else {
|
} else {
|
||||||
lineLength++
|
linepos++
|
||||||
word = true
|
if prevRuneIsSpace {
|
||||||
|
count.WordCount++
|
||||||
|
}
|
||||||
|
prevRuneIsSpace = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
count.MaxLineLength = lineLength
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConcurrentComplexChunkCounter(chunks <-chan []byte, counts chan<- ComplexCount) {
|
func ConcurrentComplexChunkCounter(chunks <-chan ComplexChunk, counts chan<- ComplexCount) {
|
||||||
var totalCount ComplexCount
|
var totalCount ComplexCount
|
||||||
for chunk := range chunks {
|
for chunk := range chunks {
|
||||||
count := GetComplexCount(chunk)
|
count := GetComplexCount(chunk)
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const BufferSize = 1024 * 1024
|
const BufferSize = 1024 * 1024 * 4
|
||||||
|
|
||||||
type Counter struct {
|
type Counter struct {
|
||||||
Words int64
|
Words int64
|
||||||
@ -35,7 +35,7 @@ func Count(filename string, cw, cc, cl, cb, mll bool) {
|
|||||||
processLine := cw || cc
|
processLine := cw || cc
|
||||||
|
|
||||||
var c = &Counter{}
|
var c = &Counter{}
|
||||||
numWorkers := runtime.NumCPU()
|
numWorkers := 2 //runtime.NumCPU()
|
||||||
|
|
||||||
if cl && !processLine {
|
if cl && !processLine {
|
||||||
c.Lines = CountLines(file, numWorkers)
|
c.Lines = CountLines(file, numWorkers)
|
||||||
@ -60,7 +60,7 @@ func Count(filename string, cw, cc, cl, cb, mll bool) {
|
|||||||
fmt.Printf("%d ", c.Words)
|
fmt.Printf("%d ", c.Words)
|
||||||
}
|
}
|
||||||
if cc {
|
if cc {
|
||||||
fmt.Printf("%d ", c.Words)
|
fmt.Printf("%d ", c.Chars)
|
||||||
}
|
}
|
||||||
if cb {
|
if cb {
|
||||||
fmt.Printf("%d ", c.Bytes)
|
fmt.Printf("%d ", c.Bytes)
|
||||||
@ -104,17 +104,18 @@ func CountLines(file *os.File, numWorkers int) int64 {
|
|||||||
func CountComplex(file *os.File, numWorkers int) *Counter {
|
func CountComplex(file *os.File, numWorkers int) *Counter {
|
||||||
counter := Counter{}
|
counter := Counter{}
|
||||||
|
|
||||||
chunks := make(chan []byte, numWorkers)
|
chunks := make(chan ComplexChunk, numWorkers)
|
||||||
counts := make(chan ComplexCount, numWorkers)
|
counts := make(chan ComplexCount, numWorkers)
|
||||||
|
|
||||||
for i := 0; i < numWorkers; i++ {
|
for i := 0; i < numWorkers; i++ {
|
||||||
go ConcurrentComplexChunkCounter(chunks, counts)
|
go ConcurrentComplexChunkCounter(chunks, counts)
|
||||||
}
|
}
|
||||||
|
var lastRune rune = ' ' // Fake the first char being a space so that the first word is counted
|
||||||
for {
|
for {
|
||||||
buf := make([]byte, BufferSize)
|
buf := make([]byte, BufferSize)
|
||||||
count, err := file.Read(buf)
|
count, err := file.Read(buf)
|
||||||
chunks <- buf[:count]
|
chunks <- ComplexChunk{lastRune, buf[:count]}
|
||||||
|
lastRune, _ = utf8.DecodeLastRune(buf[:count])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user