1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-24 08:22:14 +02:00
json-iterator/iter_object.go

253 lines
5.8 KiB
Go
Raw Normal View History

package jsoniter
import (
"fmt"
"unicode"
)
2017-07-09 10:09:23 +02:00
// ReadObject read one field from object.
// If object ended, returns empty string.
// Otherwise, returns the field name.
func (iter *Iterator) ReadObject() (ret string) {
c := iter.nextToken()
switch c {
case 'n':
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('u', 'l', 'l')
return "" // null
case '{':
c = iter.nextToken()
2017-01-20 06:56:49 +02:00
if c == '"' {
iter.unreadByte()
2018-02-14 04:31:55 +02:00
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
2018-02-14 04:31:55 +02:00
return field
}
2017-01-20 06:56:49 +02:00
if c == '}' {
return "" // end of object
}
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
2017-01-20 06:56:49 +02:00
return
case ',':
2018-02-14 04:31:55 +02:00
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
2018-02-14 04:31:55 +02:00
return field
case '}':
return "" // end of object
default:
2017-06-20 09:11:01 +02:00
iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c})))
return
}
}
// CaseInsensitive
func (iter *Iterator) readFieldHash() int64 {
2017-02-09 07:35:58 +02:00
hash := int64(0x811c9dc5)
2017-02-08 07:46:28 +02:00
c := iter.nextToken()
if c != '"' {
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
return 0
}
for {
for i := iter.head; i < iter.tail; i++ {
// require ascii string and no escape
b := iter.buf[i]
if b == '\\' {
iter.head = i
for _, b := range iter.readStringSlowPath() {
if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
}
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
2017-02-08 07:46:28 +02:00
}
return hash
}
if b == '"' {
iter.head = i + 1
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return hash
2017-02-08 07:46:28 +02:00
}
if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
b += 'a' - 'A'
2017-02-08 07:46:28 +02:00
}
hash ^= int64(b)
hash *= 0x1000193
}
if !iter.loadMore() {
iter.ReportError("readFieldHash", `incomplete field name`)
return 0
2017-02-08 07:46:28 +02:00
}
}
}
func calcHash(str string, caseSensitive bool) int64 {
2017-02-09 07:35:58 +02:00
hash := int64(0x811c9dc5)
2017-02-08 07:46:28 +02:00
for _, b := range str {
if caseSensitive {
hash ^= int64(b)
} else {
hash ^= int64(unicode.ToLower(b))
}
2017-02-08 07:46:28 +02:00
hash *= 0x1000193
}
return int64(hash)
2017-02-08 07:46:28 +02:00
}
2017-07-09 10:09:23 +02:00
// ReadObjectCB read object with callback, the key is ascii only and field name not copied
2017-01-20 06:56:49 +02:00
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
c := iter.nextToken()
var field string
2017-01-20 06:56:49 +02:00
if c == '{' {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
2018-02-14 04:31:55 +02:00
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
2017-01-20 06:56:49 +02:00
return false
}
2017-07-18 03:45:25 +02:00
c = iter.nextToken()
for c == ',' {
2018-02-14 04:31:55 +02:00
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
2017-01-20 06:56:49 +02:00
return false
}
2017-07-18 03:45:25 +02:00
c = iter.nextToken()
}
if c != '}' {
iter.ReportError("ReadObjectCB", `object not ended with }`)
return false
2017-01-20 06:56:49 +02:00
}
return true
}
if c == '}' {
return true
}
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c}))
2017-01-20 06:56:49 +02:00
return false
}
if c == 'n' {
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('u', 'l', 'l')
2017-01-20 06:56:49 +02:00
return true // null
}
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
2017-01-20 06:56:49 +02:00
return false
}
2017-07-09 10:09:23 +02:00
// ReadMapCB read map with callback, the key can be any string
func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
c := iter.nextToken()
if c == '{' {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
field := iter.ReadString()
if iter.nextToken() != ':' {
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return false
}
if !callback(iter, field) {
return false
}
2017-07-18 03:45:25 +02:00
c = iter.nextToken()
for c == ',' {
field = iter.ReadString()
if iter.nextToken() != ':' {
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return false
}
if !callback(iter, field) {
return false
}
2017-07-18 03:45:25 +02:00
c = iter.nextToken()
}
if c != '}' {
iter.ReportError("ReadMapCB", `object not ended with }`)
return false
}
return true
}
if c == '}' {
return true
}
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
return false
}
if c == 'n' {
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('u', 'l', 'l')
return true // null
}
2017-10-10 02:57:02 +02:00
iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
return false
}
func (iter *Iterator) readObjectStart() bool {
c := iter.nextToken()
if c == '{' {
c = iter.nextToken()
if c == '}' {
return false
}
iter.unreadByte()
return true
2017-05-23 12:46:11 +02:00
} else if c == 'n' {
2017-07-10 09:23:35 +02:00
iter.skipThreeBytes('u', 'l', 'l')
2017-05-23 12:46:11 +02:00
return false
}
2017-10-10 02:57:02 +02:00
iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))
return false
}
2017-01-20 06:40:52 +02:00
func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {
str := iter.ReadStringAsSlice()
if iter.skipWhitespacesWithoutLoadMore() {
2017-01-20 06:40:52 +02:00
if ret == nil {
ret = make([]byte, len(str))
copy(ret, str)
}
if !iter.loadMore() {
return
}
}
if iter.buf[iter.head] != ':' {
2017-10-10 02:57:02 +02:00
iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))
return
}
iter.head++
if iter.skipWhitespacesWithoutLoadMore() {
2017-01-20 06:40:52 +02:00
if ret == nil {
ret = make([]byte, len(str))
copy(ret, str)
}
if !iter.loadMore() {
return
}
}
2017-01-20 06:40:52 +02:00
if ret == nil {
return str
}
return ret
}