podman
267 строк · 6.2 Кб
1package jsoniter2
3import (4"fmt"5"strings"6)
7
8// ReadObject read one field from object.
9// If object ended, returns empty string.
10// Otherwise, returns the field name.
11func (iter *Iterator) ReadObject() (ret string) {12c := iter.nextToken()13switch c {14case 'n':15iter.skipThreeBytes('u', 'l', 'l')16return "" // null17case '{':18c = iter.nextToken()19if c == '"' {20iter.unreadByte()21field := iter.ReadString()22c = iter.nextToken()23if c != ':' {24iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))25}26return field27}28if c == '}' {29return "" // end of object30}31iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))32return33case ',':34field := iter.ReadString()35c = iter.nextToken()36if c != ':' {37iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))38}39return field40case '}':41return "" // end of object42default:43iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c})))44return45}46}
47
48// CaseInsensitive
49func (iter *Iterator) readFieldHash() int64 {50hash := int64(0x811c9dc5)51c := iter.nextToken()52if c != '"' {53iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))54return 055}56for {57for i := iter.head; i < iter.tail; i++ {58// require ascii string and no escape59b := iter.buf[i]60if b == '\\' {61iter.head = i62for _, b := range iter.readStringSlowPath() {63if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {64b += 'a' - 'A'65}66hash ^= int64(b)67hash *= 0x100019368}69c = iter.nextToken()70if c != ':' {71iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))72return 073}74return hash75}76if b == '"' {77iter.head = i + 178c = iter.nextToken()79if c != ':' {80iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))81return 082}83return hash84}85if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {86b += 'a' - 'A'87}88hash ^= int64(b)89hash *= 0x100019390}91if !iter.loadMore() {92iter.ReportError("readFieldHash", `incomplete field name`)93return 094}95}96}
97
98func calcHash(str string, caseSensitive bool) int64 {99if !caseSensitive {100str = strings.ToLower(str)101}102hash := int64(0x811c9dc5)103for _, b := range []byte(str) {104hash ^= int64(b)105hash *= 0x1000193106}107return int64(hash)108}
109
110// ReadObjectCB read object with callback, the key is ascii only and field name not copied
111func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {112c := iter.nextToken()113var field string114if c == '{' {115if !iter.incrementDepth() {116return false117}118c = iter.nextToken()119if c == '"' {120iter.unreadByte()121field = iter.ReadString()122c = iter.nextToken()123if c != ':' {124iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))125}126if !callback(iter, field) {127iter.decrementDepth()128return false129}130c = iter.nextToken()131for c == ',' {132field = iter.ReadString()133c = iter.nextToken()134if c != ':' {135iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))136}137if !callback(iter, field) {138iter.decrementDepth()139return false140}141c = iter.nextToken()142}143if c != '}' {144iter.ReportError("ReadObjectCB", `object not ended with }`)145iter.decrementDepth()146return false147}148return iter.decrementDepth()149}150if c == '}' {151return iter.decrementDepth()152}153iter.ReportError("ReadObjectCB", `expect " after {, but found `+string([]byte{c}))154iter.decrementDepth()155return false156}157if c == 'n' {158iter.skipThreeBytes('u', 'l', 'l')159return true // null160}161iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))162return false163}
164
165// ReadMapCB read map with callback, the key can be any string
166func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {167c := iter.nextToken()168if c == '{' {169if !iter.incrementDepth() {170return false171}172c = iter.nextToken()173if c == '"' {174iter.unreadByte()175field := iter.ReadString()176if iter.nextToken() != ':' {177iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))178iter.decrementDepth()179return false180}181if !callback(iter, field) {182iter.decrementDepth()183return false184}185c = iter.nextToken()186for c == ',' {187field = iter.ReadString()188if iter.nextToken() != ':' {189iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))190iter.decrementDepth()191return false192}193if !callback(iter, field) {194iter.decrementDepth()195return false196}197c = iter.nextToken()198}199if c != '}' {200iter.ReportError("ReadMapCB", `object not ended with }`)201iter.decrementDepth()202return false203}204return iter.decrementDepth()205}206if c == '}' {207return iter.decrementDepth()208}209iter.ReportError("ReadMapCB", `expect " after {, but found `+string([]byte{c}))210iter.decrementDepth()211return false212}213if c == 'n' {214iter.skipThreeBytes('u', 'l', 'l')215return true // null216}217iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))218return false219}
220
221func (iter *Iterator) readObjectStart() bool {222c := iter.nextToken()223if c == '{' {224c = iter.nextToken()225if c == '}' {226return false227}228iter.unreadByte()229return true230} else if c == 'n' {231iter.skipThreeBytes('u', 'l', 'l')232return false233}234iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))235return false236}
237
238func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {239str := iter.ReadStringAsSlice()240if iter.skipWhitespacesWithoutLoadMore() {241if ret == nil {242ret = make([]byte, len(str))243copy(ret, str)244}245if !iter.loadMore() {246return247}248}249if iter.buf[iter.head] != ':' {250iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))251return252}253iter.head++254if iter.skipWhitespacesWithoutLoadMore() {255if ret == nil {256ret = make([]byte, len(str))257copy(ret, str)258}259if !iter.loadMore() {260return261}262}263if ret == nil {264return str265}266return ret267}
268