package json
import (
"bytes"
"io"
"os"
)
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scan scanner
err os.Error
}
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
func (dec *Decoder) Decode(v interface{}) os.Error {
if dec.err != nil {
return dec.err
}
n, err := dec.readValue()
if err != nil {
return err
}
dec.d.init(dec.buf[0:n])
err = dec.d.unmarshal(v)
rest := copy(dec.buf, dec.buf[n:])
dec.buf = dec.buf[0:rest]
return err
}
func (dec *Decoder) readValue() (int, os.Error) {
dec.scan.reset()
scanp := 0
var err os.Error
Input:
for {
for i, c := range dec.buf[scanp:] {
v := dec.scan.step(&dec.scan, int(c))
if v == scanEnd {
scanp += i
break Input
}
if v == scanEndObject && dec.scan.step(&dec.scan, ' ') == scanEnd {
scanp += i + 1
break Input
}
if v == scanError {
dec.err = dec.scan.err
return 0, dec.scan.err
}
}
scanp = len(dec.buf)
if err != nil {
if err == os.EOF {
if dec.scan.step(&dec.scan, ' ') == scanEnd {
break Input
}
if nonSpace(dec.buf) {
err = io.ErrUnexpectedEOF
}
}
dec.err = err
return 0, err
}
const minRead = 512
if cap(dec.buf)-len(dec.buf) < minRead {
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
copy(newBuf, dec.buf)
dec.buf = newBuf
}
var n int
n, err = dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
dec.buf = dec.buf[0 : len(dec.buf)+n]
}
return scanp, nil
}
func nonSpace(b []byte) bool {
for _, c := range b {
if !isSpace(int(c)) {
return true
}
}
return false
}
type Encoder struct {
w io.Writer
e encodeState
err os.Error
}
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w}
}
func (enc *Encoder) Encode(v interface{}) os.Error {
if enc.err != nil {
return enc.err
}
enc.e.Reset()
err := enc.e.marshal(v)
if err != nil {
return err
}
enc.e.WriteByte('\n')
if _, err = enc.w.Write(enc.e.Bytes()); err != nil {
enc.err = err
}
return err
}
type RawMessage []byte
func (m *RawMessage) MarshalJSON() ([]byte, os.Error) {
return *m, nil
}
func (m *RawMessage) UnmarshalJSON(data []byte) os.Error {
if m == nil {
return os.NewError("json.RawMessage: UnmarshalJSON on nil pointer")
}
*m = bytes.Add((*m)[0:0], data)
return nil
}
var _ Marshaler = (*RawMessage)(nil)
var _ Unmarshaler = (*RawMessage)(nil)