Last active
September 25, 2016 05:33
-
-
Save lestrrat/94c2e5179999343400a24dfa4649a59f to your computer and use it in GitHub Desktop.
おもしろそうだったので自分もwc書いてみたけど、元のCで書かれたwcをあんまり改良するところがなかった…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"runtime/pprof" | |
"sync" | |
"unicode" | |
"unicode/utf8" | |
) | |
type result struct { | |
err error | |
filename string | |
bytes int | |
lines int | |
words int | |
} | |
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") | |
var showbytes = flag.Bool("c", false, "print bytes") | |
var showlines = flag.Bool("l", false, "print lines") | |
var showwords = flag.Bool("w", false, "print words") | |
var domulti = false | |
func main() { | |
flag.Parse() | |
if *cpuprofile != "" { | |
f, err := os.Create(*cpuprofile) | |
if err != nil { | |
log.Fatal(err) | |
} | |
pprof.StartCPUProfile(f) | |
defer pprof.StopCPUProfile() | |
} | |
if *showwords { | |
domulti = true | |
} else if !*showlines && !*showwords && !*showbytes { | |
domulti = true | |
*showlines = true | |
*showwords = true | |
*showbytes = true | |
} | |
var wg sync.WaitGroup | |
results := make(chan *result, flag.NArg()) | |
for i := 0; i < flag.NArg(); i++ { | |
f := flag.Arg(i) | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
countFile(results, f) | |
}() | |
} | |
wg.Wait() | |
close(results) | |
var total result | |
total.filename = "total" | |
for r := range results { | |
format(r) | |
total.bytes += r.bytes | |
total.words += r.words | |
total.lines += r.lines | |
} | |
format(&total) | |
} | |
func countFile(ch chan *result, fn string) { | |
r := result{filename: fn} | |
defer func() { | |
ch <- &r | |
}() | |
if !domulti && *showlines { | |
f, err := os.Open(fn) | |
if err != nil { | |
r.err = err | |
return | |
} | |
defer f.Close() | |
buf := make([]byte, 8192) | |
for { | |
n, err := f.Read(buf) | |
if n > 0 { | |
for _, b := range buf[:n] { | |
if b == '\n' { | |
r.lines++ | |
} | |
} | |
} | |
switch err { | |
case nil: | |
case io.EOF: | |
return | |
default: | |
r.err = err | |
return | |
} | |
} | |
return | |
} | |
if *showbytes || domulti { | |
st, err := os.Stat(fn) | |
if err != nil { | |
r.err = err | |
return | |
} else { | |
r.bytes = int(st.Size()) | |
} | |
} | |
if domulti { | |
f, err := os.Open(fn) | |
if err != nil { | |
r.err = err | |
return | |
} | |
defer f.Close() | |
gotsp := true | |
buf := make([]byte, 8192) | |
for { | |
n, err := f.Read(buf) | |
for i := 0; i < n; { | |
v, nv := utf8.DecodeRune(buf[i:n]) | |
switch { | |
case unicode.IsSpace(v): | |
if v == '\n' { | |
r.lines++ | |
} | |
gotsp = true | |
default: | |
if gotsp { | |
gotsp = false | |
r.words++ | |
} | |
} | |
i += nv | |
} | |
switch err { | |
case nil: | |
case io.EOF: | |
return | |
default: | |
r.err = err | |
return | |
} | |
} | |
} | |
} | |
func format(r *result) { | |
if r.err != nil { | |
log.Printf("%s", r.err) | |
return | |
} | |
if *showlines { | |
fmt.Printf(" %7d", r.lines) | |
} | |
if *showwords { | |
fmt.Printf(" %7d", r.words) | |
} | |
if *showbytes { | |
fmt.Printf(" %7d", r.bytes) | |
} | |
fmt.Printf(" %s\n", r.filename) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment