123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package jsoniter
- import (
- "fmt"
- "io"
- "reflect"
- "unsafe"
- )
- func decoderOfSlice(typ reflect.Type) (Decoder, error) {
- decoder, err := decoderOfType(typ.Elem())
- if err != nil {
- return nil, err
- }
- return &sliceDecoder{typ, typ.Elem(), decoder}, nil
- }
- func encoderOfSlice(typ reflect.Type) (Encoder, error) {
- encoder, err := encoderOfType(typ.Elem())
- if err != nil {
- return nil, err
- }
- if typ.Elem().Kind() == reflect.Map {
- encoder = &optionalEncoder{encoder}
- }
- return &sliceEncoder{typ, typ.Elem(), encoder}, nil
- }
- type sliceEncoder struct {
- sliceType reflect.Type
- elemType reflect.Type
- elemEncoder Encoder
- }
- func (encoder *sliceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
- slice := (*sliceHeader)(ptr)
- if slice.Len == 0 {
- stream.WriteEmptyArray()
- return
- }
- stream.WriteArrayStart()
- elemPtr := uintptr(slice.Data)
- encoder.elemEncoder.encode(unsafe.Pointer(elemPtr), stream)
- for i := 1; i < slice.Len; i++ {
- stream.WriteMore()
- elemPtr += encoder.elemType.Size()
- encoder.elemEncoder.encode(unsafe.Pointer(elemPtr), stream)
- }
- stream.WriteArrayEnd()
- if stream.Error != nil && stream.Error != io.EOF {
- stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
- }
- }
- func (encoder *sliceEncoder) encodeInterface(val interface{}, stream *Stream) {
- writeToStream(val, stream, encoder)
- }
- func (encoder *sliceEncoder) isEmpty(ptr unsafe.Pointer) bool {
- slice := (*sliceHeader)(ptr)
- return slice.Len == 0
- }
- type sliceDecoder struct {
- sliceType reflect.Type
- elemType reflect.Type
- elemDecoder Decoder
- }
- // sliceHeader is a safe version of SliceHeader used within this package.
- type sliceHeader struct {
- Data unsafe.Pointer
- Len int
- Cap int
- }
- func (decoder *sliceDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
- 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) {
- slice := (*sliceHeader)(ptr)
- reuseSlice(slice, decoder.sliceType, 4)
- if !iter.ReadArray() {
- return
- }
- offset := uintptr(0)
- decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
- if !iter.ReadArray() {
- slice.Len = 1
- return
- }
- offset += decoder.elemType.Size()
- decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
- if !iter.ReadArray() {
- slice.Len = 2
- return
- }
- offset += decoder.elemType.Size()
- decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
- if !iter.ReadArray() {
- slice.Len = 3
- return
- }
- offset += decoder.elemType.Size()
- decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
- slice.Len = 4
- for iter.ReadArray() {
- growOne(slice, decoder.sliceType, decoder.elemType)
- offset += decoder.elemType.Size()
- decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
- }
- }
- // 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
- }
- newCap := slice.Cap
- if newCap == 0 {
- newCap = 1
- } else {
- for newCap < newLen {
- if slice.Len < 1024 {
- newCap += newCap
- } else {
- newCap += newCap / 4
- }
- }
- }
- dst := unsafe.Pointer(reflect.MakeSlice(sliceType, newLen, newCap).Pointer())
- // copy old array into new array
- originalBytesCount := uintptr(slice.Len) * elementType.Size()
- srcPtr := (*[1 << 30]byte)(slice.Data)
- dstPtr := (*[1 << 30]byte)(dst)
- for i := uintptr(0); i < originalBytesCount; i++ {
- dstPtr[i] = srcPtr[i]
- }
- slice.Len = newLen
- slice.Cap = newCap
- slice.Data = dst
- }
- func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
- if expectedCap <= slice.Cap {
- return
- }
- dst := unsafe.Pointer(reflect.MakeSlice(sliceType, 0, expectedCap).Pointer())
- slice.Cap = expectedCap
- slice.Data = dst
- }
|