Skip to content

Instantly share code, notes, and snippets.

@jmank88
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmank88/5e08e791678303c4dea1 to your computer and use it in GitHub Desktop.
Save jmank88/5e08e791678303c4dea1 to your computer and use it in GitHub Desktop.
package bench
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
"strconv"
)
const (
bufferSize = 100
)
//TODO doc
func Find(path, s string) (string, error) {
if len(s) == 0 {
return "", errors.New("")
}
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()
runes := []rune(s)
myReader := &MyReader{
reader: bufio.NewReader(f),
history: make([]rune, len(runes)),
}
row := 1
col := 0
var buf bytes.Buffer
matchIndex := 0
defer func() {
if r := recover(); r != nil {
fmt.Println("asdf: ", r)
panic(r)
}
}()
for {
current, err := myReader.ReadRune()
if err == io.EOF {
break
}
if current == '\n' {
// start fresh on next row
row++
col = -1
matchIndex = 0
} else if current == runes[matchIndex] {
if matchIndex == len(runes)-1 {
// rewind to start of match
myReader.UnRead(matchIndex)
col -= matchIndex
matchIndex = 0
// record match
buf.WriteRune(',')
buf.WriteString(strconv.FormatInt(int64(row), 10))
buf.WriteRune(':')
buf.WriteString(strconv.FormatInt(int64(col), 10))
} else {
// not done yet, advance match
matchIndex++
}
} else if matchIndex > 0 {
// failed match, rewind to start of match
myReader.UnRead(matchIndex)
col -= matchIndex
matchIndex = 0
}
//next
col++
}
result := buf.String()
if len(result) > 0 {
// ignore the first comma
result = result[1:]
}
return result, nil
}
type MyReader struct {
reader *bufio.Reader
history []rune
// last returned rune
currentIndex int
// last read rune
latestIndex int
}
func (m *MyReader) UnRead(offset int) {
m.currentIndex -= offset
if m.currentIndex < 0 {
m.currentIndex += len(m.history)
}
}
func (m *MyReader) ReadRune() (rune, error) {
var err error
doRead := m.currentIndex == m.latestIndex
m.currentIndex++
if m.currentIndex == len(m.history) {
m.currentIndex = 0
}
if doRead {
m.latestIndex = m.currentIndex
m.history[m.latestIndex], _, err = m.reader.ReadRune()
}
return m.history[m.currentIndex], err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment