diff --git a/decode.go b/decode.go index cdae7b4..4517346 100644 --- a/decode.go +++ b/decode.go @@ -162,8 +162,6 @@ type decodeState struct { data []byte off int // read offset in data scan scanner - tmpstr string // scratch space to avoid some allocations - op int savedError error } @@ -184,14 +182,6 @@ func (d *decodeState) error(err error) { panic(err) } -// saveError saves the first err it is called with, -// for reporting at the end of the unmarshal. -func (d *decodeState) saveError(err error) { - if d.savedError == nil { - d.savedError = err - } -} - // skip reads d.data until it hits the given op code func (d *decodeState) skip() { //seekOp int) { var skipScan scanner @@ -337,7 +327,7 @@ func (d *decodeState) integer(v reflect.Value) { case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { - d.saveError(&UnmarshalTypeError{"integer " + s, v.Type()}) + d.error(&UnmarshalTypeError{"integer " + s, v.Type()}) } v.SetFloat(n) @@ -411,7 +401,6 @@ func (d *decodeState) string(v reflect.Value) { case reflect.Interface: if v.NumMethod() != 0 { d.error(&UnmarshalTypeError{"string", v.Type()}) - return } x := d.readString() v.Set(reflect.ValueOf(x)) @@ -420,6 +409,7 @@ func (d *decodeState) string(v reflect.Value) { // list consumes a list from d.data[d.off-1:], decoding into the value v. func (d *decodeState) list(v reflect.Value) { + // Check type of target. switch v.Kind() { case reflect.Interface: @@ -432,37 +422,23 @@ func (d *decodeState) list(v reflect.Value) { // Otherwilse it's invalid fallthrough default: - d.saveError(&UnmarshalTypeError{"list", v.Type()}) - return + d.error(&UnmarshalTypeError{"list", v.Type()}) case reflect.Array: case reflect.Slice: - break } - var c, i int - var f func(reflect.Value) + var c, op int + i := v.Len() Read: for { c = int(d.data[d.off]) d.off++ + op = d.scan.step(&d.scan, c) - switch d.scan.step(&d.scan, c) { - case scanEndList, scanEndValue: + switch op { + case scanEndList: break Read - - case scanBeginStringLen: - f = d.string - case scanBeginInteger: - f = d.integer - case scanBeginList: - f = d.list - case scanBeginDict: - f = d.dict - case scanError: - d.error(d.scan.err) - default: - d.error(errPhase) } // Get element of array, growing if necessary. @@ -482,12 +458,39 @@ Read: } } + var subv reflect.Value if i < v.Len() { // Decode into element. - f(v.Index(i)) + subv = v.Index(i) } else { // Ran out of fixed array: skip. - d.value(reflect.Value{}) + subv = reflect.Value{} + } + + for subv.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { + if subv.IsNil() { + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + switch op { + case scanBeginStringLen: + d.string(subv) + + case scanBeginInteger: + d.integer(subv) + + case scanBeginList: + d.list(subv) + + case scanBeginDict: + d.dict(subv) + + case scanError: + d.error(d.scan.err) + default: + d.error(errPhase) + } i++ } @@ -520,7 +523,7 @@ Read: c = int(d.data[d.off]) d.off++ - switch d.scan.step(&d.scan, c) { + switch op := d.scan.step(&d.scan, c); op { case scanEndList: break Read @@ -557,17 +560,16 @@ func (d *decodeState) dict(v reflect.Value) { // map must have string kind t := v.Type() if t.Key().Kind() != reflect.String { - d.saveError(&UnmarshalTypeError{"dictionary", v.Type()}) - break + d.error(&UnmarshalTypeError{"dictionary", v.Type()}) } if v.IsNil() { v.Set(reflect.MakeMap(t)) } + case reflect.Struct: default: - d.saveError(&UnmarshalTypeError{"dictionary", v.Type()}) - return + d.error(&UnmarshalTypeError{"dictionary", v.Type()}) } var mapElem reflect.Value diff --git a/scanner.go b/scanner.go index 15be379..5bc48ac 100644 --- a/scanner.go +++ b/scanner.go @@ -62,11 +62,6 @@ type scanner struct { // Error that happened, if any. err error - // 1-byte redo (see undo method) - redo bool - redoCode int - redoState func(*scanner, int) int - remain int strLenB []byte strLen int @@ -129,7 +124,6 @@ func (s *scanner) reset() { s.step = stateBeginValue s.parseState = s.parseState[0:0] s.err = nil - s.redo = false s.endTop = false } @@ -174,7 +168,6 @@ func (s *scanner) pushParseState(p int) { func (s *scanner) popParseState() { n := len(s.parseState) - 1 s.parseState = s.parseState[0:n] - s.redo = false if n == 0 { s.step = stateEndTop s.endTop = true @@ -191,16 +184,13 @@ func stateBeginValue(s *scanner, c int) int { s.pushParseState(parseInteger) return scanBeginInteger case 'l': - s.step = stateBeginValue + s.step = stateBeginList s.pushParseState(parseListValue) return scanBeginList case 'd': s.step = stateBeginDictKey s.pushParseState(parseDictKey) return scanBeginDict - case 'e': - s.popParseState() - return scanEndValue } if c >= '0' && c <= '9' { @@ -235,11 +225,12 @@ func stateEndValue(s *scanner, c int) int { return stateBeginDictKey(s, c) case parseListValue: - s.step = stateBeginValue if c == 'e' { s.popParseState() return scanEndList } + s.step = stateBeginValue + //s.pushParseState(parseListValue) return stateBeginValue(s, c) } return s.error(c, "") @@ -291,6 +282,14 @@ func stateParseString(s *scanner, c int) int { return scanParseString } +func stateBeginList(s *scanner, c int) int { + if c == 'e' { + s.popParseState() + return scanEndList + } + return stateBeginValue(s, c) +} + func stateParseKeyLen(s *scanner, c int) int { if c == ':' { var err error