fixed lists
This commit is contained in:
parent
9659acd38b
commit
a1653e0f3a
80
decode.go
80
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
|
||||
|
|
23
scanner.go
23
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
|
||||
|
|
Loading…
Reference in New Issue