OSDN Git Service

libgo: Update to weekly.2011-11-01.
[pf3gnuchains/gcc-fork.git] / libgo / go / gob / decoder.go
index f7c994f..1d526e3 100644 (file)
@@ -5,6 +5,7 @@
 package gob
 
 import (
+       "bufio"
        "bytes"
        "io"
        "os"
@@ -21,15 +22,21 @@ type Decoder struct {
        wireType     map[typeId]*wireType                    // map from remote ID to local description
        decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
        ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
-       countState   *decodeState                            // reads counts from wire
+       freeList     *decoderState                           // list of free decoderStates; avoids reallocation
        countBuf     []byte                                  // used for decoding integers while parsing messages
        tmp          []byte                                  // temporary storage for i/o; saves reallocating
        err          os.Error
 }
 
 // NewDecoder returns a new decoder that reads from the io.Reader.
+// If r does not also implement io.ByteReader, it will be wrapped in a
+// bufio.Reader.
 func NewDecoder(r io.Reader) *Decoder {
        dec := new(Decoder)
+       // We use the ability to read bytes as a plausible surrogate for buffering.
+       if _, ok := r.(io.ByteReader); !ok {
+               r = bufio.NewReader(r)
+       }
        dec.r = r
        dec.wireType = make(map[typeId]*wireType)
        dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
@@ -43,13 +50,13 @@ func NewDecoder(r io.Reader) *Decoder {
 func (dec *Decoder) recvType(id typeId) {
        // Have we already seen this type?  That's an error
        if id < firstUserId || dec.wireType[id] != nil {
-               dec.err = os.ErrorString("gob: duplicate type received")
+               dec.err = os.NewError("gob: duplicate type received")
                return
        }
 
        // Type:
        wire := new(wireType)
-       dec.err = dec.decodeValue(tWireType, reflect.NewValue(wire))
+       dec.decodeValue(tWireType, reflect.ValueOf(wire))
        if dec.err != nil {
                return
        }
@@ -57,6 +64,8 @@ func (dec *Decoder) recvType(id typeId) {
        dec.wireType[id] = wire
 }
 
+var errBadCount = os.NewError("invalid message length")
+
 // recvMessage reads the next count-delimited item from the input. It is the converse
 // of Encoder.writeMessage. It returns false on EOF or other error reading the message.
 func (dec *Decoder) recvMessage() bool {
@@ -66,6 +75,10 @@ func (dec *Decoder) recvMessage() bool {
                dec.err = err
                return false
        }
+       if nbytes >= 1<<31 {
+               dec.err = errBadCount
+               return false
+       }
        dec.readMessage(int(nbytes))
        return dec.err == nil
 }
@@ -142,7 +155,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
                // will be absorbed by recvMessage.)
                if dec.buf.Len() > 0 {
                        if !isInterface {
-                               dec.err = os.ErrorString("extra data in buffer")
+                               dec.err = os.NewError("extra data in buffer")
                                break
                        }
                        dec.nextUint()
@@ -154,28 +167,34 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
 // Decode reads the next value from the connection and stores
 // it in the data represented by the empty interface value.
 // If e is nil, the value will be discarded. Otherwise,
-// the value underlying e must either be the correct type for the next
-// data item received, and must be a pointer.
+// the value underlying e must be a pointer to the
+// correct type for the next data item received.
 func (dec *Decoder) Decode(e interface{}) os.Error {
        if e == nil {
-               return dec.DecodeValue(nil)
+               return dec.DecodeValue(reflect.Value{})
        }
-       value := reflect.NewValue(e)
+       value := reflect.ValueOf(e)
        // 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.err = os.ErrorString("gob: attempt to decode into a non-pointer")
+               dec.err = os.NewError("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, or it may be nil, which means the
-// value will be discarded.
-func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
+// DecodeValue reads the next value from the connection.
+// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
+// Otherwise, it stores the value into v.  In that case, v must represent
+// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
+func (dec *Decoder) DecodeValue(v reflect.Value) os.Error {
+       if v.IsValid() {
+               if v.Kind() == reflect.Ptr && !v.IsNil() {
+                       // That's okay, we'll store through the pointer.
+               } else if !v.CanSet() {
+                       return os.NewError("gob: DecodeValue of unassignable value")
+               }
+       }
        // Make sure we're single-threaded through here.
        dec.mutex.Lock()
        defer dec.mutex.Unlock()
@@ -184,7 +203,7 @@ func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
        dec.err = nil
        id := dec.decodeTypeSequence(false)
        if dec.err == nil {
-               dec.err = dec.decodeValue(id, value)
+               dec.decodeValue(id, v)
        }
        return dec.err
 }