Initial complex counter
This commit is contained in:
parent
05a7cdd9d7
commit
8bf0a25c88
58
pkg/wc/complex-counter.go
Normal file
58
pkg/wc/complex-counter.go
Normal file
@ -0,0 +1,58 @@
|
||||
package wc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type ComplexCount struct {
|
||||
CharCount int64
|
||||
WordCount int64
|
||||
LineCount int64
|
||||
MaxLineLength int64
|
||||
}
|
||||
|
||||
func GetComplexCount(chunk []byte) ComplexCount {
|
||||
var count = ComplexCount{}
|
||||
word := false
|
||||
var lineLength int64
|
||||
runes := bytes.Runes(chunk)
|
||||
for _, b := range runes {
|
||||
count.CharCount++
|
||||
if b == '\n' {
|
||||
if lineLength > count.MaxLineLength {
|
||||
count.MaxLineLength = lineLength
|
||||
}
|
||||
lineLength = 0
|
||||
count.LineCount++
|
||||
if word {
|
||||
word = false
|
||||
count.WordCount++
|
||||
}
|
||||
} else if unicode.IsSpace(b) {
|
||||
lineLength++
|
||||
if word {
|
||||
word = false
|
||||
count.WordCount++
|
||||
}
|
||||
} else {
|
||||
lineLength++
|
||||
word = true
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func ConcurrentComplexChunkCounter(chunks <-chan []byte, counts chan<- ComplexCount) {
|
||||
var totalCount ComplexCount
|
||||
for chunk := range chunks {
|
||||
count := GetComplexCount(chunk)
|
||||
totalCount.CharCount += count.CharCount
|
||||
totalCount.WordCount += count.WordCount
|
||||
totalCount.LineCount += count.LineCount
|
||||
if count.MaxLineLength > totalCount.MaxLineLength {
|
||||
totalCount.MaxLineLength = count.MaxLineLength
|
||||
}
|
||||
}
|
||||
counts <- totalCount
|
||||
}
|
||||
@ -31,18 +31,49 @@ func Count(filename string, cw, cc, cl, cb, mll bool) {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
size := fi.Size()
|
||||
|
||||
processLine := cw || cc
|
||||
|
||||
var c = &Counter{}
|
||||
numWorkers := runtime.NumCPU()
|
||||
|
||||
if cl && !processLine {
|
||||
c.Lines = CountLines(file, numWorkers)
|
||||
} else {
|
||||
|
||||
c = CountComplex(file, numWorkers)
|
||||
}
|
||||
|
||||
if cb {
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
c.Bytes = fi.Size()
|
||||
}
|
||||
|
||||
if cl {
|
||||
fmt.Printf("%d ", c.Lines)
|
||||
}
|
||||
if cw {
|
||||
fmt.Printf("%d ", c.Words)
|
||||
}
|
||||
if cc {
|
||||
fmt.Printf("%d ", c.Words)
|
||||
}
|
||||
if cb {
|
||||
fmt.Printf("%d ", c.Bytes)
|
||||
}
|
||||
if mll {
|
||||
fmt.Printf("%d ", c.MaxLineLength)
|
||||
}
|
||||
fmt.Printf("%s\n", filename)
|
||||
}
|
||||
|
||||
func CountLines(file *os.File, numWorkers int) int64 {
|
||||
var lines int64
|
||||
|
||||
chunks := make(chan []byte, numWorkers)
|
||||
counts := make(chan int64, numWorkers)
|
||||
|
||||
@ -50,7 +81,6 @@ func Count(filename string, cw, cc, cl, cb, mll bool) {
|
||||
go ConcurrentChunkCounter(chunks, counts)
|
||||
}
|
||||
|
||||
if cl && !processLine {
|
||||
for {
|
||||
buf := make([]byte, BufferSize)
|
||||
bytes, err := file.Read(buf)
|
||||
@ -65,45 +95,44 @@ func Count(filename string, cw, cc, cl, cb, mll bool) {
|
||||
}
|
||||
close(chunks)
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
c.Lines += <-counts
|
||||
lines += <-counts
|
||||
}
|
||||
close(counts)
|
||||
return lines
|
||||
}
|
||||
|
||||
if cb {
|
||||
c.Bytes = size
|
||||
func CountComplex(file *os.File, numWorkers int) *Counter {
|
||||
counter := Counter{}
|
||||
|
||||
chunks := make(chan []byte, numWorkers)
|
||||
counts := make(chan ComplexCount, numWorkers)
|
||||
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
go ConcurrentComplexChunkCounter(chunks, counts)
|
||||
}
|
||||
|
||||
if c.Lines > 0 {
|
||||
fmt.Printf("%d ", c.Lines)
|
||||
for {
|
||||
buf := make([]byte, BufferSize)
|
||||
count, err := file.Read(buf)
|
||||
chunks <- buf[:count]
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
if c.Words > 0 {
|
||||
fmt.Printf("%d ", c.Words)
|
||||
}
|
||||
if c.Chars > 0 {
|
||||
fmt.Printf("%d ", c.Words)
|
||||
}
|
||||
if c.Bytes > 0 {
|
||||
fmt.Printf("%d ", c.Bytes)
|
||||
close(chunks)
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
count := <-counts
|
||||
counter.Lines += count.LineCount
|
||||
counter.Words += count.WordCount
|
||||
counter.Chars += count.CharCount
|
||||
if count.MaxLineLength > counter.MaxLineLength {
|
||||
counter.MaxLineLength = count.MaxLineLength
|
||||
}
|
||||
if c.MaxLineLength > 0 {
|
||||
fmt.Printf("%d ", c.MaxLineLength)
|
||||
}
|
||||
fmt.Printf("%s\n", filename)
|
||||
close(counts)
|
||||
return &counter
|
||||
}
|
||||
|
||||
//func (c *Counter) CountLines() {
|
||||
// for {
|
||||
// _, p, err := c.FileReader.ReadLine()
|
||||
// if err != nil && err != io.EOF {
|
||||
// panic(err)
|
||||
// }
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// }
|
||||
// if !p {
|
||||
// c.Lines++
|
||||
// }
|
||||
// }
|
||||
// c.Lines--
|
||||
//}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user