1
0
mirror of https://github.com/json-iterator/go.git synced 2024-12-03 08:45:22 +02:00
json-iterator/reflect_map.go

343 lines
9.0 KiB
Go
Raw Normal View History

2017-05-24 08:34:00 +02:00
package jsoniter
import (
2018-02-24 16:04:41 +02:00
"fmt"
2018-02-28 11:09:30 +02:00
"github.com/modern-go/reflect2"
"io"
2017-06-06 17:27:00 +02:00
"reflect"
2017-06-17 15:11:23 +02:00
"sort"
2017-06-06 17:27:00 +02:00
"unsafe"
2017-05-24 08:34:00 +02:00
)
2018-02-22 04:12:08 +02:00
func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder {
mapType := typ.(*reflect2.UnsafeMapType)
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key())
elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem())
2018-02-19 16:53:42 +02:00
return &mapDecoder{
mapType: mapType,
keyType: mapType.Key(),
elemType: mapType.Elem(),
keyDecoder: keyDecoder,
elemDecoder: elemDecoder,
}
}
2018-02-22 04:12:08 +02:00
func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
mapType := typ.(*reflect2.UnsafeMapType)
2018-02-21 11:59:41 +02:00
if ctx.sortMapKeys {
2018-02-18 16:49:06 +02:00
return &sortKeysMapEncoder{
2018-02-22 04:12:08 +02:00
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
2018-02-18 16:49:06 +02:00
}
}
return &mapEncoder{
2018-02-22 04:12:08 +02:00
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
2018-02-18 16:49:06 +02:00
}
}
2018-02-22 04:12:08 +02:00
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
2018-07-22 05:51:51 +02:00
decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ)
if decoder != nil {
return decoder
}
for _, extension := range ctx.extraExtensions {
decoder := extension.CreateMapKeyDecoder(typ)
if decoder != nil {
return decoder
}
}
2018-02-19 16:53:42 +02:00
switch typ.Kind() {
case reflect.String:
2018-02-22 04:12:08 +02:00
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
2018-02-19 16:53:42 +02:00
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
2018-02-22 04:12:08 +02:00
typ = reflect2.DefaultTypeOfKind(typ.Kind())
2018-02-21 11:59:41 +02:00
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
2018-02-19 16:53:42 +02:00
default:
2018-02-22 04:12:08 +02:00
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{
&unmarshalerDecoder{
valType: ptrType,
},
}
}
if typ.Implements(unmarshalerType) {
return &unmarshalerDecoder{
valType: typ,
}
}
if ptrType.Implements(textUnmarshalerType) {
2018-02-19 16:53:42 +02:00
return &referenceDecoder{
&textUnmarshalerDecoder{
2018-02-22 04:12:08 +02:00
valType: ptrType,
2018-02-19 16:53:42 +02:00
},
}
}
if typ.Implements(textUnmarshalerType) {
2018-02-19 16:53:42 +02:00
return &textUnmarshalerDecoder{
2018-02-22 04:12:08 +02:00
valType: typ,
2018-02-19 16:53:42 +02:00
}
}
return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
2018-02-22 04:12:08 +02:00
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
2018-07-22 05:51:51 +02:00
encoder := ctx.encoderExtension.CreateMapKeyEncoder(typ)
if encoder != nil {
return encoder
}
for _, extension := range ctx.extraExtensions {
encoder := extension.CreateMapKeyEncoder(typ)
if encoder != nil {
return encoder
}
}
2018-02-18 16:49:06 +02:00
switch typ.Kind() {
case reflect.String:
2018-02-22 04:12:08 +02:00
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
2018-02-18 16:49:06 +02:00
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
2018-02-22 04:12:08 +02:00
typ = reflect2.DefaultTypeOfKind(typ.Kind())
2018-02-21 11:59:41 +02:00
return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
2018-02-18 16:49:06 +02:00
default:
if typ == textMarshalerType {
return &directTextMarshalerEncoder{
2018-02-22 04:12:08 +02:00
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
2018-02-18 16:49:06 +02:00
}
}
if typ.Implements(textMarshalerType) {
return &textMarshalerEncoder{
2018-02-22 04:12:08 +02:00
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
2018-02-18 16:49:06 +02:00
}
}
if typ.Kind() == reflect.Interface {
return &dynamicMapKeyEncoder{ctx, typ}
}
2018-02-18 16:49:06 +02:00
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
2017-05-24 08:34:00 +02:00
type mapDecoder struct {
2018-02-19 16:53:42 +02:00
mapType *reflect2.UnsafeMapType
keyType reflect2.Type
elemType reflect2.Type
keyDecoder ValDecoder
elemDecoder ValDecoder
2017-05-24 08:34:00 +02:00
}
2017-06-20 09:11:01 +02:00
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
2018-02-19 16:53:42 +02:00
mapType := decoder.mapType
c := iter.nextToken()
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
*(*unsafe.Pointer)(ptr) = nil
mapType.UnsafeSet(ptr, mapType.UnsafeNew())
2017-06-26 04:20:49 +02:00
return
}
2018-02-19 16:53:42 +02:00
if mapType.UnsafeIsNil(ptr) {
mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
2017-05-24 08:34:00 +02:00
}
2018-02-19 16:53:42 +02:00
if c != '{' {
iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
return
}
c = iter.nextToken()
if c == '}' {
return
}
if c != '"' {
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
return
}
iter.unreadByte()
key := decoder.keyType.UnsafeNew()
decoder.keyDecoder.Decode(key, iter)
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return
}
elem := decoder.elemType.UnsafeNew()
decoder.elemDecoder.Decode(elem, iter)
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
key := decoder.keyType.UnsafeNew()
decoder.keyDecoder.Decode(key, iter)
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return
2017-06-05 17:53:48 +02:00
}
2018-02-19 16:53:42 +02:00
elem := decoder.elemType.UnsafeNew()
decoder.elemDecoder.Decode(elem, iter)
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
}
if c != '}' {
iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c}))
}
}
type numericMapKeyDecoder struct {
decoder ValDecoder
}
func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
if c != '"' {
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
return
}
decoder.decoder.Decode(ptr, iter)
c = iter.nextToken()
if c != '"' {
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
return
}
2017-05-24 08:34:00 +02:00
}
2018-02-18 16:49:06 +02:00
type numericMapKeyEncoder struct {
encoder ValEncoder
}
func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.writeByte('"')
encoder.encoder.Encode(ptr, stream)
stream.writeByte('"')
}
func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type dynamicMapKeyEncoder struct {
ctx *ctx
valType reflect2.Type
}
func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := encoder.valType.UnsafeIndirect(ptr)
encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
}
func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
obj := encoder.valType.UnsafeIndirect(ptr)
return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
}
2017-05-24 08:34:00 +02:00
type mapEncoder struct {
2018-02-18 16:49:06 +02:00
mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder
elemEncoder ValEncoder
2017-05-24 08:34:00 +02:00
}
2017-06-20 09:11:01 +02:00
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
2019-09-19 14:11:30 +02:00
if *(*unsafe.Pointer)(ptr) == nil {
stream.WriteNil()
return
}
2017-05-24 08:34:00 +02:00
stream.WriteObjectStart()
2018-02-18 16:49:06 +02:00
iter := encoder.mapType.UnsafeIterate(ptr)
for i := 0; iter.HasNext(); i++ {
2017-05-24 08:34:00 +02:00
if i != 0 {
stream.WriteMore()
}
2018-02-18 16:49:06 +02:00
key, elem := iter.UnsafeNext()
encoder.keyEncoder.Encode(key, stream)
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
2018-02-18 16:49:06 +02:00
encoder.elemEncoder.Encode(elem, stream)
2017-05-24 08:34:00 +02:00
}
stream.WriteObjectEnd()
}
2017-06-20 09:11:01 +02:00
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
2018-02-18 16:49:06 +02:00
iter := encoder.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
2017-06-05 18:09:33 +02:00
}
2017-06-16 10:46:30 +02:00
type sortKeysMapEncoder struct {
2018-02-18 16:49:06 +02:00
mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder
elemEncoder ValEncoder
2017-06-16 10:46:30 +02:00
}
2017-06-20 09:11:01 +02:00
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
2018-02-18 16:49:06 +02:00
if *(*unsafe.Pointer)(ptr) == nil {
2018-02-16 09:42:37 +02:00
stream.WriteNil()
return
}
2018-02-18 16:49:06 +02:00
stream.WriteObjectStart()
mapIter := encoder.mapType.UnsafeIterate(ptr)
subStream := stream.cfg.BorrowStream(nil)
subIter := stream.cfg.BorrowIterator(nil)
keyValues := encodedKeyValues{}
for mapIter.HasNext() {
key, elem := mapIter.UnsafeNext()
subStreamIndex := subStream.Buffered()
2018-02-18 16:49:06 +02:00
encoder.keyEncoder.Encode(key, subStream)
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
stream.Error = subStream.Error
}
encodedKey := subStream.Buffer()[subStreamIndex:]
2018-02-18 16:49:06 +02:00
subIter.ResetBytes(encodedKey)
decodedKey := subIter.ReadString()
if stream.indention > 0 {
subStream.writeTwoBytes(byte(':'), byte(' '))
} else {
subStream.writeByte(':')
2017-06-26 04:42:47 +02:00
}
2018-02-18 16:49:06 +02:00
encoder.elemEncoder.Encode(elem, subStream)
keyValues = append(keyValues, encodedKV{
key: decodedKey,
keyValue: subStream.Buffer()[subStreamIndex:],
2018-02-18 16:49:06 +02:00
})
2017-06-26 04:42:47 +02:00
}
2018-02-18 16:49:06 +02:00
sort.Sort(keyValues)
for i, keyValue := range keyValues {
2017-06-16 10:46:30 +02:00
if i != 0 {
stream.WriteMore()
}
2018-02-18 16:49:06 +02:00
stream.Write(keyValue.keyValue)
2017-06-16 10:46:30 +02:00
}
stream.WriteObjectEnd()
2018-02-18 16:49:06 +02:00
stream.cfg.ReturnStream(subStream)
stream.cfg.ReturnIterator(subIter)
2017-06-16 10:46:30 +02:00
}
2018-02-18 16:49:06 +02:00
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
iter := encoder.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
2017-06-26 04:42:47 +02:00
}
2017-06-16 10:46:30 +02:00
2018-02-18 16:49:06 +02:00
type encodedKeyValues []encodedKV
2017-06-16 10:46:30 +02:00
2018-02-18 16:49:06 +02:00
type encodedKV struct {
key string
keyValue []byte
2017-06-16 10:46:30 +02:00
}
2018-02-18 16:49:06 +02:00
func (sv encodedKeyValues) Len() int { return len(sv) }
func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }