mirror of
https://github.com/json-iterator/go.git
synced 2024-11-27 08:30:57 +02:00
105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
package jsoniter
|
|
|
|
import (
|
|
"unsafe"
|
|
"reflect"
|
|
)
|
|
|
|
type mapDecoder struct {
|
|
mapType reflect.Type
|
|
elemType reflect.Type
|
|
elemDecoder Decoder
|
|
mapInterface emptyInterface
|
|
}
|
|
|
|
func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
// dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
|
|
mapInterface := decoder.mapInterface
|
|
mapInterface.word = ptr
|
|
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
|
realVal := reflect.ValueOf(*realInterface).Elem()
|
|
if realVal.IsNil() {
|
|
realVal.Set(reflect.MakeMap(realVal.Type()))
|
|
}
|
|
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
|
elem := reflect.New(decoder.elemType)
|
|
decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter)
|
|
// to put into map, we have to use reflection
|
|
realVal.SetMapIndex(reflect.ValueOf(string([]byte(field))), elem.Elem())
|
|
}
|
|
}
|
|
|
|
type mapEncoder struct {
|
|
mapType reflect.Type
|
|
elemType reflect.Type
|
|
elemEncoder Encoder
|
|
mapInterface emptyInterface
|
|
}
|
|
|
|
func (encoder *mapEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
|
|
mapInterface := encoder.mapInterface
|
|
mapInterface.word = ptr
|
|
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
|
realVal := reflect.ValueOf(*realInterface)
|
|
|
|
stream.WriteObjectStart()
|
|
for i, key := range realVal.MapKeys() {
|
|
if i != 0 {
|
|
stream.WriteMore()
|
|
}
|
|
stream.WriteObjectField(key.String())
|
|
val := realVal.MapIndex(key).Interface()
|
|
encoder.elemEncoder.encodeInterface(val, stream)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
}
|
|
|
|
func (encoder *mapEncoder) encodeInterface(val interface{}, stream *Stream) {
|
|
writeToStream(val, stream, encoder)
|
|
}
|
|
|
|
func (encoder *mapEncoder) isEmpty(ptr unsafe.Pointer) bool {
|
|
mapInterface := encoder.mapInterface
|
|
mapInterface.word = ptr
|
|
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
|
realVal := reflect.ValueOf(*realInterface)
|
|
return realVal.Len() == 0
|
|
}
|
|
|
|
type mapInterfaceEncoder struct {
|
|
mapType reflect.Type
|
|
elemType reflect.Type
|
|
elemEncoder Encoder
|
|
mapInterface emptyInterface
|
|
}
|
|
|
|
func (encoder *mapInterfaceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
|
|
mapInterface := encoder.mapInterface
|
|
mapInterface.word = ptr
|
|
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
|
realVal := reflect.ValueOf(*realInterface)
|
|
|
|
stream.WriteObjectStart()
|
|
for i, key := range realVal.MapKeys() {
|
|
if i != 0 {
|
|
stream.WriteMore()
|
|
}
|
|
stream.WriteObjectField(key.String())
|
|
val := realVal.MapIndex(key).Interface()
|
|
encoder.elemEncoder.encode(unsafe.Pointer(&val), stream)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
}
|
|
|
|
func (encoder *mapInterfaceEncoder) encodeInterface(val interface{}, stream *Stream) {
|
|
writeToStream(val, stream, encoder)
|
|
}
|
|
|
|
func (encoder *mapInterfaceEncoder) isEmpty(ptr unsafe.Pointer) bool {
|
|
mapInterface := encoder.mapInterface
|
|
mapInterface.word = ptr
|
|
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
|
realVal := reflect.ValueOf(*realInterface)
|
|
|
|
return realVal.Len() == 0
|
|
} |