diff options
Diffstat (limited to 'src/pkg/gob/decoder.go')
-rw-r--r-- | src/pkg/gob/decoder.go | 121 |
1 files changed, 78 insertions, 43 deletions
diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go index cf16433eb..664001a4b 100644 --- a/src/pkg/gob/decoder.go +++ b/src/pkg/gob/decoder.go @@ -24,6 +24,8 @@ type Decoder struct { countState *decodeState // reads counts from wire buf []byte countBuf [9]byte // counts may be uint64s (unlikely!), require 9 bytes + byteBuffer *bytes.Buffer + err os.Error } // NewDecoder returns a new decoder that reads from the io.Reader. @@ -31,25 +33,32 @@ func NewDecoder(r io.Reader) *Decoder { dec := new(Decoder) dec.r = r dec.wireType = make(map[typeId]*wireType) - dec.state = newDecodeState(nil) // buffer set in Decode(); rest is unimportant + dec.state = newDecodeState(dec, &dec.byteBuffer) // buffer set in Decode() dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) dec.ignorerCache = make(map[typeId]**decEngine) return dec } +// recvType loads the definition of a type and reloads the Decoder's buffer. func (dec *Decoder) recvType(id typeId) { // Have we already seen this type? That's an error if dec.wireType[id] != nil { - dec.state.err = os.ErrorString("gob: duplicate type received") + dec.err = os.ErrorString("gob: duplicate type received") return } // Type: wire := new(wireType) - dec.state.err = dec.decode(tWireType, reflect.NewValue(wire)) + dec.err = dec.decode(tWireType, reflect.NewValue(wire)) + if dec.err != nil { + return + } // Remember we've seen this type. dec.wireType[id] = wire + + // Load the next parcel. + dec.recv() } // Decode reads the next value from the connection and stores @@ -61,69 +70,95 @@ func (dec *Decoder) Decode(e interface{}) os.Error { // If e represents a value as opposed to a pointer, the answer won't // get back to the caller. Make sure it's a pointer. if value.Type().Kind() != reflect.Ptr { - dec.state.err = os.ErrorString("gob: attempt to decode into a non-pointer") - return dec.state.err + dec.err = os.ErrorString("gob: attempt to decode into a non-pointer") + return dec.err } return dec.DecodeValue(value) } -// DecodeValue reads the next value from the connection and stores -// it in the data represented by the reflection value. -// The value must be the correct type for the next -// data item received. -func (dec *Decoder) DecodeValue(value reflect.Value) os.Error { - // Make sure we're single-threaded through here. - dec.mutex.Lock() - defer dec.mutex.Unlock() - - dec.state.err = nil - for { - // Read a count. - var nbytes uint64 - nbytes, dec.state.err = decodeUintReader(dec.r, dec.countBuf[0:]) - if dec.state.err != nil { - break - } - // Allocate the buffer. - if nbytes > uint64(len(dec.buf)) { - dec.buf = make([]byte, nbytes+1000) - } - dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes]) +// recv reads the next count-delimited item from the input. It is the converse +// of Encoder.send. +func (dec *Decoder) recv() { + // Read a count. + var nbytes uint64 + nbytes, dec.err = decodeUintReader(dec.r, dec.countBuf[0:]) + if dec.err != nil { + return + } + // Allocate the buffer. + if nbytes > uint64(len(dec.buf)) { + dec.buf = make([]byte, nbytes+1000) + } + dec.byteBuffer = bytes.NewBuffer(dec.buf[0:nbytes]) - // Read the data - _, dec.state.err = io.ReadFull(dec.r, dec.buf[0:nbytes]) - if dec.state.err != nil { - if dec.state.err == os.EOF { - dec.state.err = io.ErrUnexpectedEOF - } - break + // Read the data + _, dec.err = io.ReadFull(dec.r, dec.buf[0:nbytes]) + if dec.err != nil { + if dec.err == os.EOF { + dec.err = io.ErrUnexpectedEOF } + return + } +} +// decodeValueFromBuffer grabs the next value from the input. The Decoder's +// buffer already contains data. If the next item in the buffer is a type +// descriptor, it may be necessary to reload the buffer, but recvType does that. +func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceValue, countPresent bool) { + for dec.state.b.Len() > 0 { // Receive a type id. - id := typeId(decodeInt(dec.state)) - if dec.state.err != nil { - break - } + id := typeId(dec.state.decodeInt()) // Is it a new type? if id < 0 { // 0 is the error state, handled above // If the id is negative, we have a type. dec.recvType(-id) - if dec.state.err != nil { + if dec.err != nil { break } continue } - // No, it's a value. // Make sure the type has been defined already or is a builtin type (for // top-level singleton values). if dec.wireType[id] == nil && builtinIdToType[id] == nil { - dec.state.err = errBadType + dec.err = errBadType break } - dec.state.err = dec.decode(id, value) + // An interface value is preceded by a byte count. + if countPresent { + count := int(dec.state.decodeUint()) + if ignoreInterfaceValue { + // An interface value is preceded by a byte count. Just skip that many bytes. + dec.state.b.Next(int(count)) + break + } + // Otherwise fall through and decode it. + } + dec.err = dec.decode(id, value) break } - return dec.state.err } + +// DecodeValue reads the next value from the connection and stores +// it in the data represented by the reflection value. +// The value must be the correct type for the next +// data item received. +func (dec *Decoder) DecodeValue(value reflect.Value) os.Error { + // Make sure we're single-threaded through here. + dec.mutex.Lock() + defer dec.mutex.Unlock() + + dec.err = nil + dec.recv() + if dec.err != nil { + return dec.err + } + dec.decodeValueFromBuffer(value, false, false) + return dec.err +} + +// If debug.go is compiled into the program , debugFunc prints a human-readable +// representation of the gob data read from r by calling that file's Debug function. +// Otherwise it is nil. +var debugFunc func(io.Reader) |