1
0
mirror of https://github.com/json-iterator/go.git synced 2025-02-19 19:59:49 +02:00
json-iterator/reflect_slice.go

100 lines
2.6 KiB
Go
Raw Normal View History

2017-06-19 23:43:28 +08:00
package jsoniter
import (
"fmt"
2018-02-28 17:09:30 +08:00
"github.com/modern-go/reflect2"
2017-06-19 23:43:28 +08:00
"io"
"unsafe"
)
2018-02-22 10:12:08 +08:00
func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
2018-02-19 14:18:42 +08:00
return &sliceDecoder{sliceType, decoder}
2017-06-19 23:43:28 +08:00
}
2018-02-22 10:12:08 +08:00
func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
2018-02-18 23:27:34 +08:00
return &sliceEncoder{sliceType, encoder}
2017-06-19 23:43:28 +08:00
}
type sliceEncoder struct {
2018-02-18 23:27:34 +08:00
sliceType *reflect2.UnsafeSliceType
elemEncoder ValEncoder
2017-06-19 23:43:28 +08:00
}
2017-06-20 15:11:01 +08:00
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
2018-02-18 23:27:34 +08:00
if encoder.sliceType.UnsafeIsNil(ptr) {
2017-06-19 23:43:28 +08:00
stream.WriteNil()
return
}
2018-02-18 23:27:34 +08:00
length := encoder.sliceType.UnsafeLengthOf(ptr)
if length == 0 {
2017-06-19 23:43:28 +08:00
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
2018-02-19 14:18:42 +08:00
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
2018-02-18 23:27:34 +08:00
for i := 1; i < length; i++ {
2017-06-19 23:43:28 +08:00
stream.WriteMore()
2018-02-19 14:18:42 +08:00
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
2018-02-18 23:27:34 +08:00
encoder.elemEncoder.Encode(elemPtr, stream)
2017-06-19 23:43:28 +08:00
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
}
}
2017-06-20 15:11:01 +08:00
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
2018-02-19 14:39:57 +08:00
return encoder.sliceType.UnsafeLengthOf(ptr) == 0
2017-06-19 23:43:28 +08:00
}
type sliceDecoder struct {
2018-02-19 14:18:42 +08:00
sliceType *reflect2.UnsafeSliceType
elemDecoder ValDecoder
2017-06-19 23:43:28 +08:00
}
2017-06-20 15:11:01 +08:00
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
2017-06-19 23:43:28 +08:00
decoder.doDecode(ptr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
}
}
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
2018-02-19 14:18:42 +08:00
c := iter.nextToken()
sliceType := decoder.sliceType
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
sliceType.UnsafeSetNil(ptr)
2017-06-26 10:20:49 +08:00
return
}
2018-02-19 14:18:42 +08:00
if c != '[' {
2018-02-22 10:12:08 +08:00
iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c}))
2017-06-19 23:43:28 +08:00
return
}
2018-02-19 14:18:42 +08:00
c = iter.nextToken()
if c == ']' {
2018-02-21 07:24:22 +08:00
sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0))
2018-02-19 14:18:42 +08:00
return
2017-06-19 23:43:28 +08:00
}
2018-02-19 14:18:42 +08:00
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 != ']' {
2018-02-22 10:12:08 +08:00
iter.ReportError("decode slice", "expect ], but found "+string([]byte{c}))
2017-06-19 23:43:28 +08:00
return
}
}