1
0
mirror of https://github.com/json-iterator/go.git synced 2025-05-13 21:36:29 +02:00

use reflect2 decode slice

This commit is contained in:
Tao Wen 2018-02-19 14:18:42 +08:00
parent cbc1786a76
commit 29604bf5c3
4 changed files with 34 additions and 62 deletions

View File

@ -34,7 +34,7 @@ type Any interface {
type baseAny struct{}
func (any *baseAny) Get(path ...interface{}) Any {
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *baseAny) Size() int {

View File

@ -14,7 +14,7 @@ func (any *stringAny) Get(path ...interface{}) Any {
if len(path) == 0 {
return any
}
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *stringAny) Parse() *Iterator {

View File

@ -10,7 +10,8 @@ import (
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
return &sliceDecoder{typ, typ.Elem(), decoder}
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
return &sliceDecoder{sliceType, decoder}
}
func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
@ -35,10 +36,10 @@ func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
return
}
stream.WriteArrayStart()
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGet(ptr, 0), stream)
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
for i := 1; i < length; i++ {
stream.WriteMore()
elemPtr := encoder.sliceType.UnsafeGet(ptr, i)
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
@ -53,8 +54,7 @@ func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
type sliceDecoder struct {
sliceType reflect.Type
elemType reflect.Type
sliceType *reflect2.UnsafeSliceType
elemDecoder ValDecoder
}
@ -73,64 +73,36 @@ func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
slice := (*sliceHeader)(ptr)
if iter.ReadNil() {
slice.Len = 0
slice.Cap = 0
slice.Data = nil
c := iter.nextToken()
sliceType := decoder.sliceType
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
sliceType.UnsafeSetNil(ptr)
return
}
reuseSlice(slice, decoder.sliceType, 4)
slice.Len = 0
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
growOne(slice, decoder.sliceType, decoder.elemType)
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
offset += decoder.elemType.Size()
return true
})
}
// grow grows the slice s so that it can hold extra more values, allocating
// more capacity if needed. It also returns the old and new slice lengths.
func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
newLen := slice.Len + 1
if newLen <= slice.Cap {
slice.Len = newLen
if c != '[' {
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
return
}
newCap := slice.Cap
if newCap == 0 {
newCap = 1
} else {
for newCap < newLen {
if slice.Len < 1024 {
newCap += newCap
} else {
newCap += newCap / 4
}
}
}
newVal := reflect.MakeSlice(sliceType, newLen, newCap).Interface()
newValPtr := extractInterface(newVal).word
dst := (*sliceHeader)(newValPtr).Data
// copy old array into new array
originalBytesCount := slice.Len * int(elementType.Size())
srcSliceHeader := (unsafe.Pointer)(&sliceHeader{slice.Data, originalBytesCount, originalBytesCount})
dstSliceHeader := (unsafe.Pointer)(&sliceHeader{dst, originalBytesCount, originalBytesCount})
copy(*(*[]byte)(dstSliceHeader), *(*[]byte)(srcSliceHeader))
slice.Data = dst
slice.Len = newLen
slice.Cap = newCap
}
func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
if expectedCap <= slice.Cap {
c = iter.nextToken()
if c == ']' {
sliceType.Set(ptr, sliceType.UnsafeNew())
return
}
iter.unreadByte()
sliceType.UnsafeGrow(ptr, 1)
elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, iter)
length := 1
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
idx := length
length += 1
sliceType.UnsafeGrow(ptr, length)
elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, iter)
}
if c != ']' {
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
return
}
newVal := reflect.MakeSlice(sliceType, 0, expectedCap).Interface()
newValPtr := extractInterface(newVal).word
dst := (*sliceHeader)(newValPtr).Data
slice.Data = dst
slice.Cap = expectedCap
}

View File

@ -74,7 +74,7 @@ func init() {
(*[]jsonMarshaler)(nil),
(*[]jsonMarshalerMap)(nil),
(*[]textMarshaler)(nil),
selectedSymmetricCase{(*[]textMarshalerMap)(nil)},
(*[]textMarshalerMap)(nil),
)
}