1
0
mirror of https://github.com/json-iterator/go.git synced 2025-06-06 22:36:25 +02:00

use hash for field dispatching

This commit is contained in:
Tao Wen 2017-02-08 13:46:28 +08:00
parent 14f696c6f5
commit da7ed7809b
4 changed files with 854 additions and 116 deletions

View File

@ -122,6 +122,59 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
return return
} }
value := uint32(ind) value := uint32(ind)
if iter.tail - iter.head > 10 {
i := iter.head
ind2 := intDigits[iter.buf[i]]
if ind2 == invalidCharForNumber {
iter.head = i
return value
}
i++
ind3 := intDigits[iter.buf[i]]
if ind3 == invalidCharForNumber {
iter.head = i
return value * 10 + uint32(ind2)
}
//iter.head = i + 1
//value = value * 100 + uint32(ind2) * 10 + uint32(ind3)
i++
ind4 := intDigits[iter.buf[i]]
if ind4 == invalidCharForNumber {
iter.head = i
return value * 100 + uint32(ind2) * 10 + uint32(ind3)
}
i++
ind5 := intDigits[iter.buf[i]]
if ind5 == invalidCharForNumber {
iter.head = i
return value * 1000 + uint32(ind2) * 100 + uint32(ind3) * 10 + uint32(ind4)
}
i++
ind6 := intDigits[iter.buf[i]]
if ind6 == invalidCharForNumber {
iter.head = i
return value * 10000 + uint32(ind2) * 1000 + uint32(ind3) * 100 + uint32(ind4) * 10 + uint32(ind5)
}
i++
ind7 := intDigits[iter.buf[i]]
if ind7 == invalidCharForNumber {
iter.head = i
return value * 100000 + uint32(ind2) * 10000 + uint32(ind3) * 1000 + uint32(ind4) * 100 + uint32(ind5) * 10 + uint32(ind6)
}
i++
ind8 := intDigits[iter.buf[i]]
if ind8 == invalidCharForNumber {
iter.head = i
return value * 1000000 + uint32(ind2) * 100000 + uint32(ind3) * 10000 + uint32(ind4) * 1000 + uint32(ind5) * 100 + uint32(ind6) * 10 + uint32(ind7)
}
i++
ind9 := intDigits[iter.buf[i]]
value = value * 10000000 + uint32(ind2) * 1000000 + uint32(ind3) * 100000 + uint32(ind4) * 10000 + uint32(ind5) * 1000 + uint32(ind6) * 100 + uint32(ind7) * 10 + uint32(ind8)
iter.head = i
if ind9 == invalidCharForNumber {
return value
}
}
for { for {
for i := iter.head; i < iter.tail; i++ { for i := iter.head; i < iter.tail; i++ {
ind = intDigits[iter.buf[i]] ind = intDigits[iter.buf[i]]

View File

@ -27,6 +27,44 @@ func (iter *Iterator) ReadObject() (ret string) {
} }
} }
func (iter *Iterator) readFieldHash() int32 {
hash := 0x811c9dc5
c := iter.nextToken()
if c == '"' {
for {
for i := iter.head; i < iter.tail; i++ {
// require ascii string and no escape
b := iter.buf[i]
if b == '"' {
iter.head = i+1
c = iter.nextToken()
if c != ':' {
iter.reportError("readFieldHash", `expect :, but found ` + string([]byte{c}))
}
return int32(hash)
}
hash ^= int(b)
hash *= 0x1000193
}
if !iter.loadMore() {
iter.reportError("readFieldHash", `incomplete field name`)
return 0
}
}
}
iter.reportError("readFieldHash", `expect ", but found ` + string([]byte{c}))
return 0
}
func calcHash(str string) int32 {
hash := 0x811c9dc5
for _, b := range str {
hash ^= int(b)
hash *= 0x1000193
}
return int32(hash)
}
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
c := iter.nextToken() c := iter.nextToken()
if c == '{' { if c == '{' {

View File

@ -99,76 +99,425 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) {
fields[fieldName] = &structFieldDecoder{&field, decoder} fields[fieldName] = &structFieldDecoder{&field, decoder}
} }
} }
return createStructDecoder(typ, fields)
}
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (Decoder, error) {
knownHash := map[int32]struct{}{
0: struct{}{},
}
switch len(fields) { switch len(fields) {
case 0: case 0:
return &skipDecoder{typ}, nil return &skipDecoder{typ}, nil
case 1: case 1:
for fieldName, fieldDecoder := range fields { for fieldName, fieldDecoder := range fields {
return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil
} }
case 2: case 2:
var fieldName1 string var fieldHash1 int32
var fieldName2 string var fieldHash2 int32
var fieldDecoder1 *structFieldDecoder var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder var fieldDecoder2 *structFieldDecoder
for fieldName, fieldDecoder := range fields { for fieldName, fieldDecoder := range fields {
if fieldName1 == "" { fieldHash := calcHash(fieldName)
fieldName1 = fieldName _, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldHash1 == 0 {
fieldHash1 = fieldHash
fieldDecoder1 = fieldDecoder fieldDecoder1 = fieldDecoder
} else { } else {
fieldName2 = fieldName fieldHash2 = fieldHash
fieldDecoder2 = fieldDecoder fieldDecoder2 = fieldDecoder
} }
} }
return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil
case 3: case 3:
var fieldName1 string var fieldName1 int32
var fieldName2 string var fieldName2 int32
var fieldName3 string var fieldName3 int32
var fieldDecoder1 *structFieldDecoder var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder var fieldDecoder3 *structFieldDecoder
for fieldName, fieldDecoder := range fields { for fieldName, fieldDecoder := range fields {
if fieldName1 == "" { fieldHash := calcHash(fieldName)
fieldName1 = fieldName _, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" { } else if fieldName2 == 0 {
fieldName2 = fieldName fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder fieldDecoder2 = fieldDecoder
} else { } else {
fieldName3 = fieldName fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder fieldDecoder3 = fieldDecoder
} }
} }
return &threeFieldsStructDecoder{typ, return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
case 4: case 4:
var fieldName1 string var fieldName1 int32
var fieldName2 string var fieldName2 int32
var fieldName3 string var fieldName3 int32
var fieldName4 string var fieldName4 int32
var fieldDecoder1 *structFieldDecoder var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder var fieldDecoder4 *structFieldDecoder
for fieldName, fieldDecoder := range fields { for fieldName, fieldDecoder := range fields {
if fieldName1 == "" { fieldHash := calcHash(fieldName)
fieldName1 = fieldName _, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder fieldDecoder1 = fieldDecoder
} else if fieldName2 == "" { } else if fieldName2 == 0 {
fieldName2 = fieldName fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder fieldDecoder2 = fieldDecoder
} else if fieldName3 == "" { } else if fieldName3 == 0 {
fieldName3 = fieldName fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder fieldDecoder3 = fieldDecoder
} else { } else {
fieldName4 = fieldName fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder fieldDecoder4 = fieldDecoder
} }
} }
return &fourFieldsStructDecoder{typ, return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil fieldName4, fieldDecoder4}, nil
case 5:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
}
}
return &fiveFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
case 6:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else if fieldName5 == 0 {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
} else {
fieldName6 = fieldHash
fieldDecoder6 = fieldDecoder
}
}
return &sixFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
case 7:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
var fieldDecoder7 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else if fieldName5 == 0 {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
} else if fieldName6 == 0 {
fieldName6 = fieldHash
fieldDecoder6 = fieldDecoder
} else {
fieldName7 = fieldHash
fieldDecoder7 = fieldDecoder
}
}
return &sevenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}, nil
case 8:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
var fieldDecoder7 *structFieldDecoder
var fieldDecoder8 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else if fieldName5 == 0 {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
} else if fieldName6 == 0 {
fieldName6 = fieldHash
fieldDecoder6 = fieldDecoder
} else if fieldName7 == 0 {
fieldName7 = fieldHash
fieldDecoder7 = fieldDecoder
} else {
fieldName8 = fieldHash
fieldDecoder8 = fieldDecoder
}
}
return &eightFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
case 9:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
var fieldDecoder7 *structFieldDecoder
var fieldDecoder8 *structFieldDecoder
var fieldDecoder9 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else if fieldName5 == 0 {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
} else if fieldName6 == 0 {
fieldName6 = fieldHash
fieldDecoder6 = fieldDecoder
} else if fieldName7 == 0 {
fieldName7 = fieldHash
fieldDecoder7 = fieldDecoder
} else if fieldName8 == 0 {
fieldName8 = fieldHash
fieldDecoder8 = fieldDecoder
} else {
fieldName9 = fieldHash
fieldDecoder9 = fieldDecoder
}
}
return &nineFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
case 10:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
var fieldName10 int32
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
var fieldDecoder4 *structFieldDecoder
var fieldDecoder5 *structFieldDecoder
var fieldDecoder6 *structFieldDecoder
var fieldDecoder7 *structFieldDecoder
var fieldDecoder8 *structFieldDecoder
var fieldDecoder9 *structFieldDecoder
var fieldDecoder10 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
} else {
knownHash[fieldHash] = struct{}{}
}
if fieldName1 == 0 {
fieldName1 = fieldHash
fieldDecoder1 = fieldDecoder
} else if fieldName2 == 0 {
fieldName2 = fieldHash
fieldDecoder2 = fieldDecoder
} else if fieldName3 == 0 {
fieldName3 = fieldHash
fieldDecoder3 = fieldDecoder
} else if fieldName4 == 0 {
fieldName4 = fieldHash
fieldDecoder4 = fieldDecoder
} else if fieldName5 == 0 {
fieldName5 = fieldHash
fieldDecoder5 = fieldDecoder
} else if fieldName6 == 0 {
fieldName6 = fieldHash
fieldDecoder6 = fieldDecoder
} else if fieldName7 == 0 {
fieldName7 = fieldHash
fieldDecoder7 = fieldDecoder
} else if fieldName8 == 0 {
fieldName8 = fieldHash
fieldDecoder8 = fieldDecoder
} else if fieldName9 == 0 {
fieldName9 = fieldHash
fieldDecoder9 = fieldDecoder
} else {
fieldName10 = fieldHash
fieldDecoder10 = fieldDecoder
}
}
return &tenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}, nil
} }
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}, nil
} }
@ -218,7 +567,7 @@ func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
type oneFieldStructDecoder struct { type oneFieldStructDecoder struct {
typ reflect.Type typ reflect.Type
fieldName string fieldHash int32
fieldDecoder *structFieldDecoder fieldDecoder *structFieldDecoder
} }
@ -226,21 +575,15 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
if !iter.readObjectStart() { if !iter.readObjectStart() {
return return
} }
fieldBytes := iter.readObjectFieldAsBytes() for {
field := *(*string)(unsafe.Pointer(&fieldBytes)) if iter.readFieldHash() == decoder.fieldHash {
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter)
} else {
iter.Skip()
}
for iter.nextToken() == ',' {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
if field == decoder.fieldName {
decoder.fieldDecoder.decode(ptr, iter) decoder.fieldDecoder.decode(ptr, iter)
} else { } else {
iter.Skip() iter.Skip()
} }
if iter.nextToken() != ',' {
break
}
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@ -248,38 +591,29 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
} }
type twoFieldsStructDecoder struct { type twoFieldsStructDecoder struct {
typ reflect.Type typ reflect.Type
fieldName1 string fieldHash1 int32
fieldDecoder1 *structFieldDecoder fieldDecoder1 *structFieldDecoder
fieldName2 string fieldHash2 int32
fieldDecoder2 *structFieldDecoder fieldDecoder2 *structFieldDecoder
} }
func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() { if !iter.readObjectStart() {
return return
} }
fieldBytes := iter.readObjectFieldAsBytes() for {
field := *(*string)(unsafe.Pointer(&fieldBytes)) switch iter.readFieldHash() {
switch field { case decoder.fieldHash1:
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2:
decoder.fieldDecoder2.decode(ptr, iter)
default:
iter.Skip()
}
for iter.nextToken() == ',' {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter) decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2: case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter) decoder.fieldDecoder2.decode(ptr, iter)
default: default:
iter.Skip() iter.Skip()
} }
if iter.nextToken() != ',' {
break
}
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@ -287,44 +621,33 @@ func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator
} }
type threeFieldsStructDecoder struct { type threeFieldsStructDecoder struct {
typ reflect.Type typ reflect.Type
fieldName1 string fieldHash1 int32
fieldDecoder1 *structFieldDecoder fieldDecoder1 *structFieldDecoder
fieldName2 string fieldHash2 int32
fieldDecoder2 *structFieldDecoder fieldDecoder2 *structFieldDecoder
fieldName3 string fieldHash3 int32
fieldDecoder3 *structFieldDecoder fieldDecoder3 *structFieldDecoder
} }
func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() { if !iter.readObjectStart() {
return return
} }
fieldBytes := iter.readObjectFieldAsBytes() for {
field := *(*string)(unsafe.Pointer(&fieldBytes)) switch iter.readFieldHash() {
switch field { case decoder.fieldHash1:
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() == ',' {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter) decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2: case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter) decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3: case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter) decoder.fieldDecoder3.decode(ptr, iter)
default: default:
iter.Skip() iter.Skip()
} }
if iter.nextToken() != ',' {
break
}
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
@ -332,50 +655,349 @@ func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterat
} }
type fourFieldsStructDecoder struct { type fourFieldsStructDecoder struct {
typ reflect.Type typ reflect.Type
fieldName1 string fieldHash1 int32
fieldDecoder1 *structFieldDecoder fieldDecoder1 *structFieldDecoder
fieldName2 string fieldHash2 int32
fieldDecoder2 *structFieldDecoder fieldDecoder2 *structFieldDecoder
fieldName3 string fieldHash3 int32
fieldDecoder3 *structFieldDecoder fieldDecoder3 *structFieldDecoder
fieldName4 string fieldHash4 int32
fieldDecoder4 *structFieldDecoder fieldDecoder4 *structFieldDecoder
} }
func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() { if !iter.readObjectStart() {
return return
} }
fieldBytes := iter.readObjectFieldAsBytes() for {
field := *(*string)(unsafe.Pointer(&fieldBytes)) switch iter.readFieldHash() {
switch field { case decoder.fieldHash1:
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() == ',' {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
switch field {
case decoder.fieldName1:
decoder.fieldDecoder1.decode(ptr, iter) decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldName2: case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter) decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldName3: case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter) decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldName4: case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter) decoder.fieldDecoder4.decode(ptr, iter)
default: default:
iter.Skip() iter.Skip()
} }
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type fiveFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
}
func (decoder *fiveFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type sixFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldDecoder6 *structFieldDecoder
}
func (decoder *sixFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
case decoder.fieldHash6:
decoder.fieldDecoder6.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type sevenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldDecoder7 *structFieldDecoder
}
func (decoder *sevenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
case decoder.fieldHash6:
decoder.fieldDecoder6.decode(ptr, iter)
case decoder.fieldHash7:
decoder.fieldDecoder7.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type eightFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldDecoder8 *structFieldDecoder
}
func (decoder *eightFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
case decoder.fieldHash6:
decoder.fieldDecoder6.decode(ptr, iter)
case decoder.fieldHash7:
decoder.fieldDecoder7.decode(ptr, iter)
case decoder.fieldHash8:
decoder.fieldDecoder8.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type nineFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldDecoder9 *structFieldDecoder
}
func (decoder *nineFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
case decoder.fieldHash6:
decoder.fieldDecoder6.decode(ptr, iter)
case decoder.fieldHash7:
decoder.fieldDecoder7.decode(ptr, iter)
case decoder.fieldHash8:
decoder.fieldDecoder8.decode(ptr, iter)
case decoder.fieldHash9:
decoder.fieldDecoder9.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
}
}
type tenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldDecoder9 *structFieldDecoder
fieldHash10 int32
fieldDecoder10 *structFieldDecoder
}
func (decoder *tenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.decode(ptr, iter)
case decoder.fieldHash2:
decoder.fieldDecoder2.decode(ptr, iter)
case decoder.fieldHash3:
decoder.fieldDecoder3.decode(ptr, iter)
case decoder.fieldHash4:
decoder.fieldDecoder4.decode(ptr, iter)
case decoder.fieldHash5:
decoder.fieldDecoder5.decode(ptr, iter)
case decoder.fieldHash6:
decoder.fieldDecoder6.decode(ptr, iter)
case decoder.fieldHash7:
decoder.fieldDecoder7.decode(ptr, iter)
case decoder.fieldHash8:
decoder.fieldDecoder8.decode(ptr, iter)
case decoder.fieldHash9:
decoder.fieldDecoder9.decode(ptr, iter)
case decoder.fieldHash10:
decoder.fieldDecoder10.decode(ptr, iter)
default:
iter.Skip()
}
if iter.nextToken() != ',' {
break
}
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())

View File

@ -85,6 +85,31 @@ func Test_decode_five_fields_struct(t *testing.T) {
should.Equal("e", obj.field5) should.Equal("e", obj.field5)
} }
func Test_decode_ten_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
field1 string
field2 string
field3 string
field4 string
field5 string
field6 string
field7 string
field8 string
field9 string
field10 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.field1)
should.Nil(UnmarshalFromString(`{"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_field_with_tag(t *testing.T) { func Test_decode_struct_field_with_tag(t *testing.T) {
should := require.New(t) should := require.New(t)
type TestObject struct { type TestObject struct {