From d481fa8dfe178c16f9ad89639715ddd7309f63f8 Mon Sep 17 00:00:00 2001 From: Wim Brand Date: Thu, 17 May 2018 16:10:39 +0200 Subject: [PATCH] init --- main.go | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 main.go diff --git a/main.go b/main.go new file mode 100644 index 0000000..dc5fa88 --- /dev/null +++ b/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "bufio" + "bytes" + "io" + "os" + "runtime" + "sync" +) + +const lf = byte('\n') + +func main() { + if len(os.Args) != 2 { + print("One argument required\n") + os.Exit(1) + } + + f, err := os.Open("locate.txt") + if err != nil { + panic(err) + } + defer f.Close() + + var needle = os.Args[1] + + // To make sure all threads have ended when the program finishes + var wg sync.WaitGroup + + // Make a channel and a thread for each CPU core + var cores = runtime.NumCPU() + var linechan = make(chan []byte) + for i := 0; i < cores; i++ { + go scannerThread(linechan, []byte(needle), &wg) + wg.Add(1) + } + + var br = bufio.NewReaderSize(f, 1<<25) // reader with 32 MiB buffer + var buf = make([]byte, 1<<20) // 1 MiB buffer for searching + var remainder []byte + var nread int + + for { + nread, err = br.Read(buf) + if err != nil && err != io.EOF { + panic(err) + } + if err != io.EOF { + // Get the remainder of the last line + remainder, err = br.ReadBytes(byte('\n')) + if err != nil && err != io.EOF { + panic(err) + } + } + + linechan <- append(buf[:nread], remainder...) + + if err == io.EOF { + break + } + } + + close(linechan) + + wg.Wait() +} + +func scannerThread(linechannel chan []byte, needle []byte, wg *sync.WaitGroup) { + var line []byte + var ok bool + var start, end int + var linelen int + var i int + defer wg.Done() + for { + line, ok = <-linechannel + if !ok { + return // channel closed. we're done + } + + // This loop is for every result found, when there are no more results it stops + for i = bytes.Index(line, needle); i != -1; i = bytes.Index(line, needle) { + start, end = i, i + // needle was found, but where? + for { // find the start + if line[start] == lf { + start++ // the line feed is from the previous line, so skip it + break + } else if start == 0 { + break // result is at start of file + } + start-- + } + + for { // find the end + if line[end] == lf || end == linelen-1 { + break + } + end++ + } + + print(string(line[start:end]) + "\n") + + // Chop all of the bytes before the result off so it doesn't get + // searched again + line = line[end:] + linelen = len(line) + } + } +}