Logic complete

master
DustyP 5 years ago
parent 8bf0a25c88
commit dd2748d8ae

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

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' { if b == '\n' || b == '\r' || b == '\f' {
if lineLength > count.MaxLineLength { if linepos > lineLength {
count.MaxLineLength = lineLength lineLength = linepos
} }
lineLength = 0 linepos = 0
count.LineCount++ if b == '\n' {
if word { count.LineCount++
word = false
count.WordCount++
} }
} else if unicode.IsSpace(b) { }
lineLength++ if unicode.IsSpace(b) {
if word { if b == '\t' {
word = false linepos += 8 - (linepos % 8)
count.WordCount++ } 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…
Cancel
Save