1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-27 08:30:57 +02:00

split files

This commit is contained in:
Tao Wen 2017-01-07 07:49:50 +08:00
parent c78023531e
commit 5af8cc4b09
5 changed files with 628 additions and 638 deletions

View File

@ -6,7 +6,6 @@ import (
"io"
"reflect"
"strconv"
"strings"
"sync/atomic"
"unsafe"
)
@ -25,6 +24,71 @@ type Decoder interface {
decode(ptr unsafe.Pointer, iter *Iterator)
}
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
type ExtensionFunc func(typ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc)
type funcDecoder struct {
fun DecoderFunc
}
func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.fun(ptr, iter)
}
var DECODERS unsafe.Pointer
var typeDecoders map[string]Decoder
var fieldDecoders map[string]Decoder
var extensions []ExtensionFunc
func init() {
typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{}
extensions = []ExtensionFunc{}
atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{}))
}
func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
retry := true
for retry {
ptr := atomic.LoadPointer(&DECODERS)
cache := *(*map[reflect.Type]Decoder)(ptr)
copy := map[reflect.Type]Decoder{}
for k, v := range cache {
copy[k] = v
}
copy[cacheKey] = decoder
retry = !atomic.CompareAndSwapPointer(&DECODERS, ptr, unsafe.Pointer(&copy))
}
}
func getDecoderFromCache(cacheKey reflect.Type) Decoder {
ptr := atomic.LoadPointer(&DECODERS)
cache := *(*map[reflect.Type]Decoder)(ptr)
return cache[cacheKey]
}
// RegisterTypeDecoder can register a type for json object
func RegisterTypeDecoder(typ string, fun DecoderFunc) {
typeDecoders[typ] = &funcDecoder{fun}
}
// RegisterFieldDecoder can register a type for json field
func RegisterFieldDecoder(typ string, field string, fun DecoderFunc) {
fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = &funcDecoder{fun}
}
// RegisterExtension can register a custom extension
func RegisterExtension(extension ExtensionFunc) {
extensions = append(extensions, extension)
}
// CleanDecoders cleans decoders registered
func CleanDecoders() {
typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{}
}
type optionalDecoder struct {
valueType reflect.Type
valueDecoder Decoder
@ -46,218 +110,6 @@ func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
}
}
type generalStructDecoder struct {
typ reflect.Type
fields map[string]*structFieldDecoder
}
func (decoder *generalStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
fieldDecoder := decoder.fields[field]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.decode(ptr, iter)
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
fieldDecoder = decoder.fields[field]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.decode(ptr, iter)
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type skipDecoder struct {
typ reflect.Type
}
func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
iter.Skip()
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type oneFieldStructDecoder struct {
typ reflect.Type
fieldName string
fieldDecoder *structFieldDecoder
}
func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter)
} else {
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter)
} else {
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type twoFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
}
func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type threeFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
fieldName3 string
fieldDecoder3 *structFieldDecoder
}
func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type fourFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
fieldName3 string
fieldDecoder3 *structFieldDecoder
fieldName4 string
fieldDecoder4 *structFieldDecoder
}
func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldName4:
decoder.fieldDecoder4.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldName4:
decoder.fieldDecoder4.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type structFieldDecoder struct {
field *reflect.StructField
fieldDecoder Decoder
}
func (decoder *structFieldDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := uintptr(ptr) + decoder.field.Offset
decoder.fieldDecoder.decode(unsafe.Pointer(fieldPtr), iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error())
}
}
type mapDecoder struct {
mapType reflect.Type
elemType reflect.Type
@ -280,167 +132,6 @@ func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
}
}
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
}
var DECODERS unsafe.Pointer
func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
retry := true
for retry {
ptr := atomic.LoadPointer(&DECODERS)
cache := *(*map[reflect.Type]Decoder)(ptr)
copy := map[reflect.Type]Decoder{}
for k, v := range cache {
copy[k] = v
}
copy[cacheKey] = decoder
retry = !atomic.CompareAndSwapPointer(&DECODERS, ptr, unsafe.Pointer(&copy))
}
}
func getDecoderFromCache(cacheKey reflect.Type) Decoder {
ptr := atomic.LoadPointer(&DECODERS)
cache := *(*map[reflect.Type]Decoder)(ptr)
return cache[cacheKey]
}
var typeDecoders map[string]Decoder
var fieldDecoders map[string]Decoder
var extensions []ExtensionFunc
func init() {
typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{}
extensions = []ExtensionFunc{}
atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{}))
}
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
type ExtensionFunc func(typ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc)
type funcDecoder struct {
fun DecoderFunc
}
func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.fun(ptr, iter)
}
// RegisterTypeDecoder can register a type for json object
func RegisterTypeDecoder(typ string, fun DecoderFunc) {
typeDecoders[typ] = &funcDecoder{fun}
}
// RegisterFieldDecoder can register a type for json field
func RegisterFieldDecoder(typ string, field string, fun DecoderFunc) {
fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = &funcDecoder{fun}
}
// RegisterExtension can register a custom extension
func RegisterExtension(extension ExtensionFunc) {
extensions = append(extensions, extension)
}
// CleanDecoders cleans decoders registered
func CleanDecoders() {
typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{}
}
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *struct{}
@ -646,123 +337,6 @@ func decoderOfOptional(typ reflect.Type) (Decoder, error) {
return &optionalDecoder{typ, decoder}, nil
}
func decoderOfStruct(typ reflect.Type) (Decoder, error) {
fields := map[string]*structFieldDecoder{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
var fieldNames []string
for _, extension := range extensions {
alternativeFieldNames, fun := extension(typ, &field)
if alternativeFieldNames != nil {
fieldNames = alternativeFieldNames
}
if fun != nil {
fieldDecoders[fieldDecoderKey] = &funcDecoder{fun}
}
}
decoder := fieldDecoders[fieldDecoderKey]
tagParts := strings.Split(field.Tag.Get("json"), ",")
// if fieldNames set by extension, use theirs, otherwise try tags
if fieldNames == nil {
/// tagParts[0] always present, even if no tags
switch tagParts[0] {
case "":
fieldNames = []string{field.Name}
case "-":
fieldNames = []string{}
default:
fieldNames = []string{tagParts[0]}
}
}
if decoder == nil {
var err error
decoder, err = decoderOfPtr(field.Type)
if err != nil {
return prefix(fmt.Sprintf("{%s}", field.Name)).addTo(decoder, err)
}
}
if len(tagParts) > 1 && tagParts[1] == "string" {
decoder = &stringNumberDecoder{decoder}
}
for _, fieldName := range fieldNames {
fields[fieldName] = &structFieldDecoder{&field, decoder}
}
}
switch len(fields) {
case 0:
return &skipDecoder{typ}, nil
case 1:
for fieldName, fieldDecoder := range fields {
return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil
}
case 2:
var fieldName1 string
var fieldName2 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
}
}
return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
case 3:
var fieldName1 string
var fieldName2 string
var fieldName3 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
} else {
fieldName3 = fieldName
fieldDecoder3 = fieldDecoder
}
}
return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
case 4:
var fieldName1 string
var fieldName2 string
var fieldName3 string
var fieldName4 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
} else if fieldName3 == "" {
fieldName3 = fieldName
fieldDecoder3 = fieldDecoder
} else {
fieldName4 = fieldName
fieldDecoder4 = fieldDecoder
}
}
return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil
}
return &generalStructDecoder{typ, fields}, nil
}
func decoderOfSlice(typ reflect.Type) (Decoder, error) {
decoder, err := decoderOfPtr(typ.Elem())
if err != nil {

104
feature_reflect_array.go Normal file
View File

@ -0,0 +1,104 @@
package jsoniter
import (
"unsafe"
"reflect"
"io"
"fmt"
)
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
}

338
feature_reflect_object.go Normal file
View File

@ -0,0 +1,338 @@
package jsoniter
import (
"io"
"fmt"
"reflect"
"unsafe"
"strings"
)
func decoderOfStruct(typ reflect.Type) (Decoder, error) {
fields := map[string]*structFieldDecoder{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
var fieldNames []string
for _, extension := range extensions {
alternativeFieldNames, fun := extension(typ, &field)
if alternativeFieldNames != nil {
fieldNames = alternativeFieldNames
}
if fun != nil {
fieldDecoders[fieldDecoderKey] = &funcDecoder{fun}
}
}
decoder := fieldDecoders[fieldDecoderKey]
tagParts := strings.Split(field.Tag.Get("json"), ",")
// if fieldNames set by extension, use theirs, otherwise try tags
if fieldNames == nil {
/// tagParts[0] always present, even if no tags
switch tagParts[0] {
case "":
fieldNames = []string{field.Name}
case "-":
fieldNames = []string{}
default:
fieldNames = []string{tagParts[0]}
}
}
if decoder == nil {
var err error
decoder, err = decoderOfPtr(field.Type)
if err != nil {
return prefix(fmt.Sprintf("{%s}", field.Name)).addTo(decoder, err)
}
}
if len(tagParts) > 1 && tagParts[1] == "string" {
decoder = &stringNumberDecoder{decoder}
}
for _, fieldName := range fieldNames {
fields[fieldName] = &structFieldDecoder{&field, decoder}
}
}
switch len(fields) {
case 0:
return &skipDecoder{typ}, nil
case 1:
for fieldName, fieldDecoder := range fields {
return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil
}
case 2:
var fieldName1 string
var fieldName2 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
}
}
return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
case 3:
var fieldName1 string
var fieldName2 string
var fieldName3 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
} else {
fieldName3 = fieldName
fieldDecoder3 = fieldDecoder
}
}
return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
case 4:
var fieldName1 string
var fieldName2 string
var fieldName3 string
var fieldName4 string
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
if fieldName1 == "" {
fieldName1 = fieldName
fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" {
fieldName2 = fieldName
fieldDecoder2 = fieldDecoder
} else if fieldName3 == "" {
fieldName3 = fieldName
fieldDecoder3 = fieldDecoder
} else {
fieldName4 = fieldName
fieldDecoder4 = fieldDecoder
}
}
return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil
}
return &generalStructDecoder{typ, fields}, nil
}
type generalStructDecoder struct {
typ reflect.Type
fields map[string]*structFieldDecoder
}
func (decoder *generalStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
fieldDecoder := decoder.fields[field]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.decode(ptr, iter)
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
fieldDecoder = decoder.fields[field]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.decode(ptr, iter)
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type skipDecoder struct {
typ reflect.Type
}
func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
iter.Skip()
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type oneFieldStructDecoder struct {
typ reflect.Type
fieldName string
fieldDecoder *structFieldDecoder
}
func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter)
} else {
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter)
} else {
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type twoFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
}
func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type threeFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
fieldName3 string
fieldDecoder3 *structFieldDecoder
}
func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type fourFieldsStructDecoder struct {
typ reflect.Type
fieldName1 string
fieldDecoder1 *structFieldDecoder
fieldName2 string
fieldDecoder2 *structFieldDecoder
fieldName3 string
fieldDecoder3 *structFieldDecoder
fieldName4 string
fieldDecoder4 *structFieldDecoder
}
func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
field := iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldName4:
decoder.fieldDecoder4.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
field = iter.readObjectField()
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldName4:
decoder.fieldDecoder4.decode(ptr, iter)
default:
iter.Skip()
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type structFieldDecoder struct {
field *reflect.StructField
fieldDecoder Decoder
}
func (decoder *structFieldDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := uintptr(ptr) + decoder.field.Offset
decoder.fieldDecoder.decode(unsafe.Pointer(fieldPtr), iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error())
}
}

View File

@ -0,0 +1,112 @@
package jsoniter
import (
"testing"
"github.com/json-iterator/go/require"
)
func Test_decode_one_field_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "hello"}`, &obj))
should.Equal("hello", obj.field1)
}
func Test_decode_two_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
}
func Test_decode_three_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
}
func Test_decode_four_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
field4 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
should.Equal("d", obj.field4)
}
func Test_decode_five_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
field4 string
field5 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d", "field5": "e"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
should.Equal("d", obj.field4)
should.Equal("e", obj.field5)
}
func Test_decode_struct_with_optional_field(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 *string
field2 *string
}
obj := TestObject{}
UnmarshalString(`{"field1": null, "field2": "world"}`, &obj)
should.Nil(obj.field1)
should.Equal("world", *obj.field2)
}
func Test_decode_struct_field_with_tag(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string `json:"field-1"`
Field2 string `json:"-"`
Field3 int `json:",string"`
}
obj := TestObject{Field2: "world"}
UnmarshalString(`{"field-1": "hello", "field2": "", "Field3": "100"}`, &obj)
should.Equal("hello", obj.Field1)
should.Equal("world", obj.Field2)
should.Equal(100, obj.Field3)
}

View File

@ -8,159 +8,21 @@ import (
"github.com/json-iterator/go/require"
)
func Test_reflect_one_field_struct(t *testing.T) {
func Test_decode_slice(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "hello"}`, &obj))
should.Equal("hello", obj.field1)
}
func Test_reflect_two_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
}
func Test_reflect_three_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
}
func Test_reflect_four_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
field4 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
should.Equal("d", obj.field4)
}
func Test_reflect_five_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
field4 string
field5 string
}
obj := TestObject{}
should.Nil(UnmarshalString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d", "field5": "e"}`, &obj))
should.Equal("a", obj.field1)
should.Equal("b", obj.field2)
should.Equal("c", obj.field3)
should.Equal("d", obj.field4)
should.Equal("e", obj.field5)
}
func Test_struct_with_optional_field(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 *string
field2 *string
}
obj := TestObject{}
UnmarshalString(`{"field1": null, "field2": "world"}`, &obj)
should.Nil(obj.field1)
should.Equal("world", *obj.field2)
}
type StructOfTag struct {
Field1 string `json:"field-1"`
Field2 string `json:"-"`
Field3 int `json:",string"`
}
func Test_reflect_struct_tag_field(t *testing.T) {
iter := ParseString(`{"field-1": "hello", "field2": "", "Field3": "100"}`)
Struct := StructOfTag{Field2: "world"}
iter.Read(&Struct)
if Struct.Field1 != "hello" {
fmt.Println(iter.Error)
t.Fatal(Struct.Field1)
}
if Struct.Field2 != "world" {
fmt.Println(iter.Error)
t.Fatal(Struct.Field2)
}
if Struct.Field3 != 100 {
fmt.Println(iter.Error)
t.Fatal(Struct.Field3)
}
}
func Test_reflect_slice(t *testing.T) {
iter := ParseString(`["hello", "world"]`)
slice := make([]string, 0, 5)
iter.Read(&slice)
if len(slice) != 2 {
fmt.Println(iter.Error)
t.Fatal(len(slice))
}
if slice[0] != "hello" {
fmt.Println(iter.Error)
t.Fatal(slice[0])
}
if slice[1] != "world" {
fmt.Println(iter.Error)
t.Fatal(slice[1])
}
UnmarshalString(`["hello", "world"]`, &slice)
should.Equal([]string{"hello", "world"}, slice)
}
func Test_reflect_large_slice(t *testing.T) {
iter := ParseString(`[1,2,3,4,5,6,7,8,9]`)
func Test_decode_large_slice(t *testing.T) {
should := require.New(t)
slice := make([]int, 0, 1)
iter.Read(&slice)
if len(slice) != 9 {
fmt.Println(iter.Error)
t.Fatal(len(slice))
}
if slice[0] != 1 {
fmt.Println(iter.Error)
t.Fatal(slice[0])
}
if slice[8] != 9 {
fmt.Println(iter.Error)
t.Fatal(slice[8])
}
UnmarshalString(`[1,2,3,4,5,6,7,8,9]`, &slice)
should.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}, slice)
}
func Test_reflect_nested(t *testing.T) {
func Test_decode_nested(t *testing.T) {
type StructOfString struct {
field1 string
field2 string
@ -186,7 +48,7 @@ func Test_reflect_nested(t *testing.T) {
}
}
func Test_reflect_base64(t *testing.T) {
func Test_decode_base64(t *testing.T) {
iter := ParseString(`"YWJj"`)
val := []byte{}
RegisterTypeDecoder("[]uint8", func(ptr unsafe.Pointer, iter *Iterator) {