From fc170098e9e21afe4d1b592b746c97fc5f8cccd9 Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Mon, 23 Feb 2015 20:07:19 +0700 Subject: [PATCH] One buffer fits all --- buffer/buffer.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ buffer/bufferer.go | 7 ------- buffer/bytes.go | 34 ------------------------------ buffer/stream.go | 37 --------------------------------- lexer/lexer.go | 6 +++--- lexer/lexer_test.go | 4 ++-- main.go | 15 +++++++++++++- parser/parser.go | 2 +- 8 files changed, 70 insertions(+), 85 deletions(-) create mode 100644 buffer/buffer.go delete mode 100644 buffer/bufferer.go delete mode 100644 buffer/bytes.go delete mode 100644 buffer/stream.go diff --git a/buffer/buffer.go b/buffer/buffer.go new file mode 100644 index 0000000..b9c74fa --- /dev/null +++ b/buffer/buffer.go @@ -0,0 +1,50 @@ +package buffer + +import ( + "bufio" + "bytes" + "io" +) + +type ( + Buffer struct { + input *bufio.Reader + ready chan rune + } +) + +func NewBytesBuffer(b []byte) *Buffer { + return NewReaderBuffer(bytes.NewReader(b)) +} + +func NewReaderBuffer(rd io.Reader) *Buffer { + return New(bufio.NewReader(rd)) +} + +func New(input *bufio.Reader) *Buffer { + b := &Buffer{ + input: input, + ready: make(chan rune, 100), + } + go b.stream() + return b +} + +func (b *Buffer) Next() rune { + if next, ok := <-b.ready; ok { + return next + } else { + return 0 + } +} + +func (b *Buffer) stream() { + for { + if r, _, err := b.input.ReadRune(); err != nil { + close(b.ready) + break + } else { + b.ready <- r + } + } +} diff --git a/buffer/bufferer.go b/buffer/bufferer.go deleted file mode 100644 index 1c34ae4..0000000 --- a/buffer/bufferer.go +++ /dev/null @@ -1,7 +0,0 @@ -package buffer - -type ( - Bufferer interface { - Next() rune - } -) diff --git a/buffer/bytes.go b/buffer/bytes.go deleted file mode 100644 index 5f43595..0000000 --- a/buffer/bytes.go +++ /dev/null @@ -1,34 +0,0 @@ -package buffer - -import ( - "bytes" - "unicode/utf8" -) - -type ( - BytesBuffer struct { - input []byte - size uint64 - pos uint64 - } -) - -func NewBytesBuffer(input []byte) *BytesBuffer { - return &BytesBuffer{ - input: input, - size: uint64(len(input)), - } -} - -func (b *BytesBuffer) Next() rune { - var buf bytes.Buffer - for b.pos < b.size { - buf.WriteByte(b.input[b.pos]) - b.pos++ - if ok := utf8.FullRune(buf.Bytes()); ok { - r, _ := utf8.DecodeRune(buf.Bytes()) - return r - } - } - return 0 -} diff --git a/buffer/stream.go b/buffer/stream.go deleted file mode 100644 index f274a93..0000000 --- a/buffer/stream.go +++ /dev/null @@ -1,37 +0,0 @@ -package buffer - -import ( - "bytes" - "io" - "unicode/utf8" -) - -type ( - StreamBuffer struct { - input io.Reader - } -) - -func NewStreamBuffer(input io.Reader) *StreamBuffer { - return &StreamBuffer{ - input: input, - } -} - -func (b *StreamBuffer) Next() rune { - var ( - buf bytes.Buffer - ) - for { - rbuf := make([]byte, 1) - if n, err := b.input.Read(rbuf); n != 1 || err != nil { - return 0 - } - buf.Write(rbuf) - if ok := utf8.FullRune(buf.Bytes()); ok { - r, _ := utf8.DecodeRune(buf.Bytes()) - return r - } - } - return 0 -} diff --git a/lexer/lexer.go b/lexer/lexer.go index 858235d..955de20 100644 --- a/lexer/lexer.go +++ b/lexer/lexer.go @@ -12,7 +12,7 @@ import ( type ( // Holds the state of the scanner Lexer struct { - input buffer.Bufferer + input *buffer.Buffer stack []rune // Lexer stack pos int // Current stack position lineNum int // Line number @@ -59,10 +59,10 @@ const ( ) // Creates a new scanner for the input buffer -func New(input buffer.Bufferer) *Lexer { +func New(input *buffer.Buffer) *Lexer { return &Lexer{ input: input, - items: make(chan Item), + items: make(chan Item, 100), lineNum: 1, colNum: 0, } diff --git a/lexer/lexer_test.go b/lexer/lexer_test.go index a87adce..d23a60e 100644 --- a/lexer/lexer_test.go +++ b/lexer/lexer_test.go @@ -152,8 +152,8 @@ func compare(t *testing.T, reality, expectations []Item) { } } -func lex(json string) []Item { - buf := buffer.NewBytesBuffer([]byte(json)) +func lex(jstr string) []Item { + buf := buffer.NewBytesBuffer([]byte(jstr)) lex := New(buf) go lex.Run() diff --git a/main.go b/main.go index da1303a..06524ab 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "os" "strings" + "github.com/davecheney/profile" "github.com/localhots/punk/buffer" "github.com/localhots/punk/parser" ) @@ -14,8 +15,11 @@ func main() { var ( sel string verbose bool + prof string ) + flag.StringVar(&sel, "s", "", "Selector") + flag.StringVar(&prof, "prof", "", "Performance profiling output") flag.BoolVar(&verbose, "v", false, "Verbose parsing") flag.Parse() @@ -24,15 +28,24 @@ func main() { os.Exit(1) } + if prof != "" { + defer profile.Start(&profile.Config{ + CPUProfile: true, + ProfilePath: prof, + }).Stop() + } + sels := strings.Split(sel, " ") if len(sel) == 0 { sels = []string{} } - buf := buffer.NewStreamBuffer(os.Stdin) + + buf := buffer.NewReaderBuffer(os.Stdin) pars := parser.New(buf, sels) if verbose { pars.Debug() } + res := pars.ParseStream() for { if m, ok := <-res; ok { diff --git a/parser/parser.go b/parser/parser.go index d33709f..58db05f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -25,7 +25,7 @@ type ( ) // Creates a new parser -func New(buf buffer.Bufferer, sels []string) *Parser { +func New(buf *buffer.Buffer, sels []string) *Parser { return &Parser{ lex: lexer.New(buf), ctx: &context{