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:
parent
cbc1786a76
commit
29604bf5c3
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func init() {
|
||||
(*[]jsonMarshaler)(nil),
|
||||
(*[]jsonMarshalerMap)(nil),
|
||||
(*[]textMarshaler)(nil),
|
||||
selectedSymmetricCase{(*[]textMarshalerMap)(nil)},
|
||||
(*[]textMarshalerMap)(nil),
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user