diff --git a/cmd/wc-go/main.go b/cmd/wc-go/main.go index 1e7d16d..5e57081 100644 --- a/cmd/wc-go/main.go +++ b/cmd/wc-go/main.go @@ -33,6 +33,8 @@ package main // output version information and exit import ( + "fmt" + "github.com/droundy/goopt" "github.com/dustinpianalto/wc-go/pkg/wc" ) @@ -67,5 +69,11 @@ var ( func main() { goopt.Version = "v0.0.0a" goopt.Parse(nil) - wc.Count("main.go", *fWords, *fChars, *fLines, *fBytes, *fMaxLineLength) + if len(goopt.Args) == 0 { + fmt.Println(goopt.Help()) + } else { + for _, a := range goopt.Args { + wc.Count(a, *fWords, *fChars, *fLines, *fBytes, *fMaxLineLength) + } + } } diff --git a/pkg/wc/chunk.go b/pkg/wc/chunk.go new file mode 100644 index 0000000..025725a --- /dev/null +++ b/pkg/wc/chunk.go @@ -0,0 +1,19 @@ +package wc + +func GetLineCount(chunk []byte) int64 { + var count int64 + for _, b := range chunk { + if b == '\n' { + count++ + } + } + return count +} + +func ConcurrentChunkCounter(chunks <-chan []byte, counts chan<- int64) { + var totalCount int64 + for chunk := range chunks { + totalCount += GetLineCount(chunk) + } + counts <- totalCount +} diff --git a/pkg/wc/counter.go b/pkg/wc/counter.go index e0b577b..ef191b9 100644 --- a/pkg/wc/counter.go +++ b/pkg/wc/counter.go @@ -1,14 +1,15 @@ package wc import ( - "bufio" "fmt" - "log" + "io" "os" + "runtime" ) +const BufferSize = 1024 * 1024 + type Counter struct { - FileReader *bufio.Reader Words int64 Chars int64 Lines int64 @@ -27,28 +28,82 @@ func Count(filename string, cw, cc, cl, cb, mll bool) { file, err := os.Open(filename) if err != nil { fmt.Println(err) + return } defer file.Close() + fi, err := file.Stat() + if err != nil { + fmt.Println(err) + return + } + size := fi.Size() + processLine := cw || cc - var c = Counter{FileReader: bufio.NewReader(file)} - if cl && !processLine { - c.CountLines(cb) + + var c = &Counter{} + numWorkers := runtime.NumCPU() + + chunks := make(chan []byte, numWorkers) + counts := make(chan int64, numWorkers) + + for i := 0; i < numWorkers; i++ { + go ConcurrentChunkCounter(chunks, counts) } - fmt.Printf("%d %s\n", c.Lines, filename) -} -func (c *Counter) CountLines(cb bool) { - for { - r, s, err := c.FileReader.ReadRune() - log.Printf("%#v, %#v, %#v", r, s, err) - if err != nil { - break - } - if r == '\n' { - c.Lines++ + if cl && !processLine { + for { + buf := make([]byte, BufferSize) + bytes, err := file.Read(buf) + chunks <- buf[:bytes] + if err != nil { + if err == io.EOF { + break + } else { + panic(err) + } + } } - if cb { - c.Bytes += int64(s) + close(chunks) + for i := 0; i < numWorkers; i++ { + c.Lines += <-counts } + close(counts) + } + + if cb { + c.Bytes = size + } + + if c.Lines > 0 { + fmt.Printf("%d ", c.Lines) } + 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) + } + if c.MaxLineLength > 0 { + fmt.Printf("%d ", c.MaxLineLength) + } + fmt.Printf("%s\n", filename) } + +//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-- +//}