123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- //
- // Besides, jsoniter.Iterator provides a different set of interfaces
- // iterating given bytes/string/reader
- // and yielding parsed elements one by one.
- // This set of interfaces reads input as required and gives
- // better performance.
- package jsoniter
- import (
- "encoding/base64"
- "fmt"
- "io"
- )
- type ValueType int
- const (
- Invalid ValueType = iota
- String
- Number
- Nil
- Bool
- Array
- Object
- )
- var hexDigits []byte
- var valueTypes []ValueType
- func init() {
- hexDigits = make([]byte, 256)
- for i := 0; i < len(hexDigits); i++ {
- hexDigits[i] = 255
- }
- for i := '0'; i <= '9'; i++ {
- hexDigits[i] = byte(i - '0')
- }
- for i := 'a'; i <= 'f'; i++ {
- hexDigits[i] = byte((i - 'a') + 10)
- }
- for i := 'A'; i <= 'F'; i++ {
- hexDigits[i] = byte((i - 'A') + 10)
- }
- valueTypes = make([]ValueType, 256)
- for i := 0; i < len(valueTypes); i++ {
- valueTypes[i] = Invalid
- }
- valueTypes['"'] = String
- valueTypes['-'] = Number
- valueTypes['0'] = Number
- valueTypes['1'] = Number
- valueTypes['2'] = Number
- valueTypes['3'] = Number
- valueTypes['4'] = Number
- valueTypes['5'] = Number
- valueTypes['6'] = Number
- valueTypes['7'] = Number
- valueTypes['8'] = Number
- valueTypes['9'] = Number
- valueTypes['t'] = Bool
- valueTypes['f'] = Bool
- valueTypes['n'] = Nil
- valueTypes['['] = Array
- valueTypes['{'] = Object
- }
- // Iterator is a fast and flexible JSON parser
- type Iterator struct {
- reader io.Reader
- buf []byte
- head int
- tail int
- Error error
- }
- // Create creates an empty Iterator instance
- func NewIterator() *Iterator {
- return &Iterator{
- reader: nil,
- buf: nil,
- head: 0,
- tail: 0,
- }
- }
- // Parse parses a json buffer in io.Reader into an Iterator instance
- func Parse(reader io.Reader, bufSize int) *Iterator {
- return &Iterator{
- reader: reader,
- buf: make([]byte, bufSize),
- head: 0,
- tail: 0,
- }
- }
- // ParseBytes parses a json byte slice into an Iterator instance
- func ParseBytes(input []byte) *Iterator {
- return &Iterator{
- reader: nil,
- buf: input,
- head: 0,
- tail: len(input),
- }
- }
- // ParseString parses a json string into an Iterator instance
- func ParseString(input string) *Iterator {
- return ParseBytes([]byte(input))
- }
- // Reset can reset an Iterator instance for another json buffer in io.Reader
- func (iter *Iterator) Reset(reader io.Reader) *Iterator {
- iter.reader = reader
- iter.head = 0
- iter.tail = 0
- return iter
- }
- // ResetBytes can reset an Iterator instance for another json byte slice
- func (iter *Iterator) ResetBytes(input []byte) *Iterator {
- iter.reader = nil
- iter.Error = nil
- iter.buf = input
- iter.head = 0
- iter.tail = len(input)
- return iter
- }
- // WhatIsNext gets ValueType of relatively next json object
- func (iter *Iterator) WhatIsNext() ValueType {
- valueType := valueTypes[iter.nextToken()]
- iter.unreadByte()
- return valueType
- }
- func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
- for i := iter.head; i < iter.tail; i++ {
- c := iter.buf[i]
- switch c {
- case ' ', '\n', '\t', '\r':
- continue
- }
- iter.head = i
- return false
- }
- return true
- }
- func (iter *Iterator) nextToken() byte {
- // a variation of skip whitespaces, returning the next non-whitespace token
- for {
- for i := iter.head; i < iter.tail; i++ {
- c := iter.buf[i]
- switch c {
- case ' ', '\n', '\t', '\r':
- continue
- }
- iter.head = i + 1
- return c
- }
- if !iter.loadMore() {
- return 0
- }
- }
- }
- func (iter *Iterator) reportError(operation string, msg string) {
- if iter.Error != nil {
- if iter.Error != io.EOF {
- return
- }
- }
- peekStart := iter.head - 10
- if peekStart < 0 {
- peekStart = 0
- }
- iter.Error = fmt.Errorf("%s: %s, parsing %v ...%s... at %s", operation, msg, iter.head,
- string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
- }
- // CurrentBuffer gets current buffer as string
- func (iter *Iterator) CurrentBuffer() string {
- peekStart := iter.head - 10
- if peekStart < 0 {
- peekStart = 0
- }
- return fmt.Sprintf("parsing %v ...|%s|... at %s", iter.head,
- string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
- }
- func (iter *Iterator) readByte() (ret byte) {
- if iter.head == iter.tail {
- if iter.loadMore() {
- ret = iter.buf[iter.head]
- iter.head++
- return ret
- }
- return 0
- }
- ret = iter.buf[iter.head]
- iter.head++
- return ret
- }
- func (iter *Iterator) loadMore() bool {
- if iter.reader == nil {
- if iter.Error == nil {
- iter.Error = io.EOF
- }
- return false
- }
- for {
- n, err := iter.reader.Read(iter.buf)
- if n == 0 {
- if err != nil {
- if iter.Error == nil {
- iter.Error = err
- }
- return false
- }
- } else {
- iter.head = 0
- iter.tail = n
- return true
- }
- }
- }
- func (iter *Iterator) unreadByte() {
- if iter.head == 0 {
- iter.reportError("unreadByte", "unread too many bytes")
- return
- }
- iter.head--
- return
- }
- func (iter *Iterator) Read() interface{} {
- valueType := iter.WhatIsNext()
- switch valueType {
- case String:
- return iter.ReadString()
- case Number:
- return iter.ReadFloat64()
- case Nil:
- iter.skipFixedBytes(4) // null
- return nil
- case Bool:
- return iter.ReadBool()
- case Array:
- arr := []interface{}{}
- iter.ReadArrayCB(func(iter *Iterator) bool {
- arr = append(arr, iter.Read())
- return true
- })
- return arr
- case Object:
- obj := map[string]interface{}{}
- iter.ReadObjectCB(func(Iter *Iterator, field string) bool {
- obj[field] = iter.Read()
- return true
- })
- return obj
- default:
- iter.reportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
- return nil
- }
- }
- // ReadBase64 reads a json object as Base64 in byte slice
- func (iter *Iterator) ReadBase64() (ret []byte) {
- src := iter.ReadStringAsSlice()
- if iter.Error != nil {
- return
- }
- b64 := base64.StdEncoding
- ret = make([]byte, b64.DecodedLen(len(src)))
- n, err := b64.Decode(ret, src)
- if err != nil {
- iter.Error = err
- return
- }
- return ret[:n]
- }
|