252 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package jsoniter
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// 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':
 | 
						|
		iter.skipThreeBytes('u', 'l', 'l')
 | 
						|
		return "" // null
 | 
						|
	case '{':
 | 
						|
		c = iter.nextToken()
 | 
						|
		if c == '"' {
 | 
						|
			iter.unreadByte()
 | 
						|
			field := iter.ReadString()
 | 
						|
			c = iter.nextToken()
 | 
						|
			if c != ':' {
 | 
						|
				iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
			}
 | 
						|
			return field
 | 
						|
		}
 | 
						|
		if c == '}' {
 | 
						|
			return "" // end of object
 | 
						|
		}
 | 
						|
		iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
 | 
						|
		return
 | 
						|
	case ',':
 | 
						|
		field := iter.ReadString()
 | 
						|
		c = iter.nextToken()
 | 
						|
		if c != ':' {
 | 
						|
			iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
		}
 | 
						|
		return field
 | 
						|
	case '}':
 | 
						|
		return "" // end of object
 | 
						|
	default:
 | 
						|
		iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c})))
 | 
						|
		return
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// CaseInsensitive
 | 
						|
func (iter *Iterator) readFieldHash() int64 {
 | 
						|
	hash := int64(0x811c9dc5)
 | 
						|
	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
 | 
						|
				}
 | 
						|
				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
 | 
						|
			}
 | 
						|
			if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
 | 
						|
				b += 'a' - 'A'
 | 
						|
			}
 | 
						|
			hash ^= int64(b)
 | 
						|
			hash *= 0x1000193
 | 
						|
		}
 | 
						|
		if !iter.loadMore() {
 | 
						|
			iter.ReportError("readFieldHash", `incomplete field name`)
 | 
						|
			return 0
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func calcHash(str string, caseSensitive bool) int64 {
 | 
						|
	if !caseSensitive {
 | 
						|
		str = strings.ToLower(str)
 | 
						|
	}
 | 
						|
	hash := int64(0x811c9dc5)
 | 
						|
	for _, b := range []byte(str) {
 | 
						|
		hash ^= int64(b)
 | 
						|
		hash *= 0x1000193
 | 
						|
	}
 | 
						|
	return int64(hash)
 | 
						|
}
 | 
						|
 | 
						|
// ReadObjectCB read object with callback, the key is ascii only and field name not copied
 | 
						|
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
 | 
						|
	c := iter.nextToken()
 | 
						|
	var field string
 | 
						|
	if c == '{' {
 | 
						|
		c = iter.nextToken()
 | 
						|
		if c == '"' {
 | 
						|
			iter.unreadByte()
 | 
						|
			field = iter.ReadString()
 | 
						|
			c = iter.nextToken()
 | 
						|
			if c != ':' {
 | 
						|
				iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
			}
 | 
						|
			if !callback(iter, field) {
 | 
						|
				return false
 | 
						|
			}
 | 
						|
			c = iter.nextToken()
 | 
						|
			for c == ',' {
 | 
						|
				field = iter.ReadString()
 | 
						|
				c = iter.nextToken()
 | 
						|
				if c != ':' {
 | 
						|
					iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
				}
 | 
						|
				if !callback(iter, field) {
 | 
						|
					return false
 | 
						|
				}
 | 
						|
				c = iter.nextToken()
 | 
						|
			}
 | 
						|
			if c != '}' {
 | 
						|
				iter.ReportError("ReadObjectCB", `object not ended with }`)
 | 
						|
				return false
 | 
						|
			}
 | 
						|
			return true
 | 
						|
		}
 | 
						|
		if c == '}' {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
		iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c}))
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if c == 'n' {
 | 
						|
		iter.skipThreeBytes('u', 'l', 'l')
 | 
						|
		return true // null
 | 
						|
	}
 | 
						|
	iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// 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() != ':' {
 | 
						|
				iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
				return false
 | 
						|
			}
 | 
						|
			if !callback(iter, field) {
 | 
						|
				return false
 | 
						|
			}
 | 
						|
			c = iter.nextToken()
 | 
						|
			for c == ',' {
 | 
						|
				field = iter.ReadString()
 | 
						|
				if iter.nextToken() != ':' {
 | 
						|
					iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
 | 
						|
					return false
 | 
						|
				}
 | 
						|
				if !callback(iter, field) {
 | 
						|
					return false
 | 
						|
				}
 | 
						|
				c = iter.nextToken()
 | 
						|
			}
 | 
						|
			if c != '}' {
 | 
						|
				iter.ReportError("ReadMapCB", `object not ended with }`)
 | 
						|
				return false
 | 
						|
			}
 | 
						|
			return true
 | 
						|
		}
 | 
						|
		if c == '}' {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
		iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if c == 'n' {
 | 
						|
		iter.skipThreeBytes('u', 'l', 'l')
 | 
						|
		return true // null
 | 
						|
	}
 | 
						|
	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
 | 
						|
	} else if c == 'n' {
 | 
						|
		iter.skipThreeBytes('u', 'l', 'l')
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {
 | 
						|
	str := iter.ReadStringAsSlice()
 | 
						|
	if iter.skipWhitespacesWithoutLoadMore() {
 | 
						|
		if ret == nil {
 | 
						|
			ret = make([]byte, len(str))
 | 
						|
			copy(ret, str)
 | 
						|
		}
 | 
						|
		if !iter.loadMore() {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if iter.buf[iter.head] != ':' {
 | 
						|
		iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	iter.head++
 | 
						|
	if iter.skipWhitespacesWithoutLoadMore() {
 | 
						|
		if ret == nil {
 | 
						|
			ret = make([]byte, len(str))
 | 
						|
			copy(ret, str)
 | 
						|
		}
 | 
						|
		if !iter.loadMore() {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ret == nil {
 | 
						|
		return str
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 |