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{}
|
type baseAny struct{}
|
||||||
|
|
||||||
func (any *baseAny) Get(path ...interface{}) Any {
|
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 {
|
func (any *baseAny) Size() int {
|
||||||
|
@ -14,7 +14,7 @@ func (any *stringAny) Get(path ...interface{}) Any {
|
|||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return any
|
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 {
|
func (any *stringAny) Parse() *Iterator {
|
||||||
|
@ -10,7 +10,8 @@ import (
|
|||||||
|
|
||||||
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||||
decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
|
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 {
|
func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||||
@ -35,10 +36,10 @@ func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
stream.WriteArrayStart()
|
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++ {
|
for i := 1; i < length; i++ {
|
||||||
stream.WriteMore()
|
stream.WriteMore()
|
||||||
elemPtr := encoder.sliceType.UnsafeGet(ptr, i)
|
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
|
||||||
encoder.elemEncoder.Encode(elemPtr, stream)
|
encoder.elemEncoder.Encode(elemPtr, stream)
|
||||||
}
|
}
|
||||||
stream.WriteArrayEnd()
|
stream.WriteArrayEnd()
|
||||||
@ -53,8 +54,7 @@ func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sliceDecoder struct {
|
type sliceDecoder struct {
|
||||||
sliceType reflect.Type
|
sliceType *reflect2.UnsafeSliceType
|
||||||
elemType reflect.Type
|
|
||||||
elemDecoder ValDecoder
|
elemDecoder ValDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,64 +73,36 @@ func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
slice := (*sliceHeader)(ptr)
|
c := iter.nextToken()
|
||||||
if iter.ReadNil() {
|
sliceType := decoder.sliceType
|
||||||
slice.Len = 0
|
if c == 'n' {
|
||||||
slice.Cap = 0
|
iter.skipThreeBytes('u', 'l', 'l')
|
||||||
slice.Data = nil
|
sliceType.UnsafeSetNil(ptr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
reuseSlice(slice, decoder.sliceType, 4)
|
if c != '[' {
|
||||||
slice.Len = 0
|
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
|
||||||
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
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newCap := slice.Cap
|
c = iter.nextToken()
|
||||||
if newCap == 0 {
|
if c == ']' {
|
||||||
newCap = 1
|
sliceType.Set(ptr, sliceType.UnsafeNew())
|
||||||
} else {
|
return
|
||||||
for newCap < newLen {
|
}
|
||||||
if slice.Len < 1024 {
|
iter.unreadByte()
|
||||||
newCap += newCap
|
sliceType.UnsafeGrow(ptr, 1)
|
||||||
} else {
|
elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
|
||||||
newCap += newCap / 4
|
decoder.elemDecoder.Decode(elemPtr, iter)
|
||||||
}
|
length := 1
|
||||||
}
|
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
|
||||||
}
|
idx := length
|
||||||
newVal := reflect.MakeSlice(sliceType, newLen, newCap).Interface()
|
length += 1
|
||||||
newValPtr := extractInterface(newVal).word
|
sliceType.UnsafeGrow(ptr, length)
|
||||||
dst := (*sliceHeader)(newValPtr).Data
|
elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
|
||||||
// copy old array into new array
|
decoder.elemDecoder.Decode(elemPtr, iter)
|
||||||
originalBytesCount := slice.Len * int(elementType.Size())
|
}
|
||||||
srcSliceHeader := (unsafe.Pointer)(&sliceHeader{slice.Data, originalBytesCount, originalBytesCount})
|
if c != ']' {
|
||||||
dstSliceHeader := (unsafe.Pointer)(&sliceHeader{dst, originalBytesCount, originalBytesCount})
|
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
|
||||||
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 {
|
|
||||||
return
|
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),
|
(*[]jsonMarshaler)(nil),
|
||||||
(*[]jsonMarshalerMap)(nil),
|
(*[]jsonMarshalerMap)(nil),
|
||||||
(*[]textMarshaler)(nil),
|
(*[]textMarshaler)(nil),
|
||||||
selectedSymmetricCase{(*[]textMarshalerMap)(nil)},
|
(*[]textMarshalerMap)(nil),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user