1
0
Fork 0
forked from mirrors/tar-split

Optimize JSON decoding

This allows to avoid extra allocations on `ReadBytes` and
decoding buffers.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2015-11-30 09:52:44 -08:00
parent bece0c7009
commit 8b20f9161d

View file

@ -1,7 +1,6 @@
package storage package storage
import ( import (
"bufio"
"encoding/json" "encoding/json"
"errors" "errors"
"io" "io"
@ -33,31 +32,15 @@ type PackUnpacker interface {
*/ */
type jsonUnpacker struct { type jsonUnpacker struct {
r io.Reader seen seenNames
b *bufio.Reader dec *json.Decoder
isEOF bool
seen seenNames
} }
func (jup *jsonUnpacker) Next() (*Entry, error) { func (jup *jsonUnpacker) Next() (*Entry, error) {
var e Entry var e Entry
if jup.isEOF { err := jup.dec.Decode(&e)
// since ReadBytes() will return read bytes AND an EOF, we handle it this if err != nil {
// round-a-bout way so we can Unmarshal the tail with relevant errors, but
// still get an io.EOF when the stream is ended.
return nil, io.EOF
}
line, err := jup.b.ReadBytes('\n')
if err != nil && err != io.EOF {
return nil, err return nil, err
} else if err == io.EOF {
jup.isEOF = true
}
err = json.Unmarshal(line, &e)
if err != nil && jup.isEOF {
// if the remainder actually _wasn't_ a remaining json structure, then just EOF
return nil, io.EOF
} }
// check for dup name // check for dup name
@ -78,8 +61,7 @@ func (jup *jsonUnpacker) Next() (*Entry, error) {
// Each Entry read are expected to be delimited by new line. // Each Entry read are expected to be delimited by new line.
func NewJSONUnpacker(r io.Reader) Unpacker { func NewJSONUnpacker(r io.Reader) Unpacker {
return &jsonUnpacker{ return &jsonUnpacker{
r: r, dec: json.NewDecoder(r),
b: bufio.NewReader(r),
seen: seenNames{}, seen: seenNames{},
} }
} }