iter.go raw

   1  package jsoniter
   2  
   3  import (
   4  	"encoding/json"
   5  	"fmt"
   6  	"io"
   7  )
   8  
   9  // ValueType the type for JSON element
  10  type ValueType int
  11  
  12  const (
  13  	// InvalidValue invalid JSON element
  14  	InvalidValue ValueType = iota
  15  	// StringValue JSON element "string"
  16  	StringValue
  17  	// NumberValue JSON element 100 or 0.10
  18  	NumberValue
  19  	// NilValue JSON element null
  20  	NilValue
  21  	// BoolValue JSON element true or false
  22  	BoolValue
  23  	// ArrayValue JSON element []
  24  	ArrayValue
  25  	// ObjectValue JSON element {}
  26  	ObjectValue
  27  )
  28  
  29  var hexDigits []byte
  30  var valueTypes []ValueType
  31  
  32  func init() {
  33  	hexDigits = make([]byte, 256)
  34  	for i := 0; i < len(hexDigits); i++ {
  35  		hexDigits[i] = 255
  36  	}
  37  	for i := '0'; i <= '9'; i++ {
  38  		hexDigits[i] = byte(i - '0')
  39  	}
  40  	for i := 'a'; i <= 'f'; i++ {
  41  		hexDigits[i] = byte((i - 'a') + 10)
  42  	}
  43  	for i := 'A'; i <= 'F'; i++ {
  44  		hexDigits[i] = byte((i - 'A') + 10)
  45  	}
  46  	valueTypes = make([]ValueType, 256)
  47  	for i := 0; i < len(valueTypes); i++ {
  48  		valueTypes[i] = InvalidValue
  49  	}
  50  	valueTypes['"'] = StringValue
  51  	valueTypes['-'] = NumberValue
  52  	valueTypes['0'] = NumberValue
  53  	valueTypes['1'] = NumberValue
  54  	valueTypes['2'] = NumberValue
  55  	valueTypes['3'] = NumberValue
  56  	valueTypes['4'] = NumberValue
  57  	valueTypes['5'] = NumberValue
  58  	valueTypes['6'] = NumberValue
  59  	valueTypes['7'] = NumberValue
  60  	valueTypes['8'] = NumberValue
  61  	valueTypes['9'] = NumberValue
  62  	valueTypes['t'] = BoolValue
  63  	valueTypes['f'] = BoolValue
  64  	valueTypes['n'] = NilValue
  65  	valueTypes['['] = ArrayValue
  66  	valueTypes['{'] = ObjectValue
  67  }
  68  
  69  // Iterator is a io.Reader like object, with JSON specific read functions.
  70  // Error is not returned as return value, but stored as Error member on this iterator instance.
  71  type Iterator struct {
  72  	cfg              *frozenConfig
  73  	reader           io.Reader
  74  	buf              []byte
  75  	head             int
  76  	tail             int
  77  	depth            int
  78  	captureStartedAt int
  79  	captured         []byte
  80  	Error            error
  81  	Attachment       interface{} // open for customized decoder
  82  }
  83  
  84  // NewIterator creates an empty Iterator instance
  85  func NewIterator(cfg API) *Iterator {
  86  	return &Iterator{
  87  		cfg:    cfg.(*frozenConfig),
  88  		reader: nil,
  89  		buf:    nil,
  90  		head:   0,
  91  		tail:   0,
  92  		depth:  0,
  93  	}
  94  }
  95  
  96  // Parse creates an Iterator instance from io.Reader
  97  func Parse(cfg API, reader io.Reader, bufSize int) *Iterator {
  98  	return &Iterator{
  99  		cfg:    cfg.(*frozenConfig),
 100  		reader: reader,
 101  		buf:    make([]byte, bufSize),
 102  		head:   0,
 103  		tail:   0,
 104  		depth:  0,
 105  	}
 106  }
 107  
 108  // ParseBytes creates an Iterator instance from byte array
 109  func ParseBytes(cfg API, input []byte) *Iterator {
 110  	return &Iterator{
 111  		cfg:    cfg.(*frozenConfig),
 112  		reader: nil,
 113  		buf:    input,
 114  		head:   0,
 115  		tail:   len(input),
 116  		depth:  0,
 117  	}
 118  }
 119  
 120  // ParseString creates an Iterator instance from string
 121  func ParseString(cfg API, input string) *Iterator {
 122  	return ParseBytes(cfg, []byte(input))
 123  }
 124  
 125  // Pool returns a pool can provide more iterator with same configuration
 126  func (iter *Iterator) Pool() IteratorPool {
 127  	return iter.cfg
 128  }
 129  
 130  // Reset reuse iterator instance by specifying another reader
 131  func (iter *Iterator) Reset(reader io.Reader) *Iterator {
 132  	iter.reader = reader
 133  	iter.head = 0
 134  	iter.tail = 0
 135  	iter.depth = 0
 136  	return iter
 137  }
 138  
 139  // ResetBytes reuse iterator instance by specifying another byte array as input
 140  func (iter *Iterator) ResetBytes(input []byte) *Iterator {
 141  	iter.reader = nil
 142  	iter.buf = input
 143  	iter.head = 0
 144  	iter.tail = len(input)
 145  	iter.depth = 0
 146  	return iter
 147  }
 148  
 149  // WhatIsNext gets ValueType of relatively next json element
 150  func (iter *Iterator) WhatIsNext() ValueType {
 151  	valueType := valueTypes[iter.nextToken()]
 152  	iter.unreadByte()
 153  	return valueType
 154  }
 155  
 156  func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
 157  	for i := iter.head; i < iter.tail; i++ {
 158  		c := iter.buf[i]
 159  		switch c {
 160  		case ' ', '\n', '\t', '\r':
 161  			continue
 162  		}
 163  		iter.head = i
 164  		return false
 165  	}
 166  	return true
 167  }
 168  
 169  func (iter *Iterator) isObjectEnd() bool {
 170  	c := iter.nextToken()
 171  	if c == ',' {
 172  		return false
 173  	}
 174  	if c == '}' {
 175  		return true
 176  	}
 177  	iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c}))
 178  	return true
 179  }
 180  
 181  func (iter *Iterator) nextToken() byte {
 182  	// a variation of skip whitespaces, returning the next non-whitespace token
 183  	for {
 184  		for i := iter.head; i < iter.tail; i++ {
 185  			c := iter.buf[i]
 186  			switch c {
 187  			case ' ', '\n', '\t', '\r':
 188  				continue
 189  			}
 190  			iter.head = i + 1
 191  			return c
 192  		}
 193  		if !iter.loadMore() {
 194  			return 0
 195  		}
 196  	}
 197  }
 198  
 199  // ReportError record a error in iterator instance with current position.
 200  func (iter *Iterator) ReportError(operation string, msg string) {
 201  	if iter.Error != nil {
 202  		if iter.Error != io.EOF {
 203  			return
 204  		}
 205  	}
 206  	peekStart := iter.head - 10
 207  	if peekStart < 0 {
 208  		peekStart = 0
 209  	}
 210  	peekEnd := iter.head + 10
 211  	if peekEnd > iter.tail {
 212  		peekEnd = iter.tail
 213  	}
 214  	parsing := string(iter.buf[peekStart:peekEnd])
 215  	contextStart := iter.head - 50
 216  	if contextStart < 0 {
 217  		contextStart = 0
 218  	}
 219  	contextEnd := iter.head + 50
 220  	if contextEnd > iter.tail {
 221  		contextEnd = iter.tail
 222  	}
 223  	context := string(iter.buf[contextStart:contextEnd])
 224  	iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
 225  		operation, msg, iter.head-peekStart, parsing, context)
 226  }
 227  
 228  // CurrentBuffer gets current buffer as string for debugging purpose
 229  func (iter *Iterator) CurrentBuffer() string {
 230  	peekStart := iter.head - 10
 231  	if peekStart < 0 {
 232  		peekStart = 0
 233  	}
 234  	return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head,
 235  		string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
 236  }
 237  
 238  func (iter *Iterator) readByte() (ret byte) {
 239  	if iter.head == iter.tail {
 240  		if iter.loadMore() {
 241  			ret = iter.buf[iter.head]
 242  			iter.head++
 243  			return ret
 244  		}
 245  		return 0
 246  	}
 247  	ret = iter.buf[iter.head]
 248  	iter.head++
 249  	return ret
 250  }
 251  
 252  func (iter *Iterator) loadMore() bool {
 253  	if iter.reader == nil {
 254  		if iter.Error == nil {
 255  			iter.head = iter.tail
 256  			iter.Error = io.EOF
 257  		}
 258  		return false
 259  	}
 260  	if iter.captured != nil {
 261  		iter.captured = append(iter.captured,
 262  			iter.buf[iter.captureStartedAt:iter.tail]...)
 263  		iter.captureStartedAt = 0
 264  	}
 265  	for {
 266  		n, err := iter.reader.Read(iter.buf)
 267  		if n == 0 {
 268  			if err != nil {
 269  				if iter.Error == nil {
 270  					iter.Error = err
 271  				}
 272  				return false
 273  			}
 274  		} else {
 275  			iter.head = 0
 276  			iter.tail = n
 277  			return true
 278  		}
 279  	}
 280  }
 281  
 282  func (iter *Iterator) unreadByte() {
 283  	if iter.Error != nil {
 284  		return
 285  	}
 286  	iter.head--
 287  	return
 288  }
 289  
 290  // Read read the next JSON element as generic interface{}.
 291  func (iter *Iterator) Read() interface{} {
 292  	valueType := iter.WhatIsNext()
 293  	switch valueType {
 294  	case StringValue:
 295  		return iter.ReadString()
 296  	case NumberValue:
 297  		if iter.cfg.configBeforeFrozen.UseNumber {
 298  			return json.Number(iter.readNumberAsString())
 299  		}
 300  		return iter.ReadFloat64()
 301  	case NilValue:
 302  		iter.skipFourBytes('n', 'u', 'l', 'l')
 303  		return nil
 304  	case BoolValue:
 305  		return iter.ReadBool()
 306  	case ArrayValue:
 307  		arr := []interface{}{}
 308  		iter.ReadArrayCB(func(iter *Iterator) bool {
 309  			var elem interface{}
 310  			iter.ReadVal(&elem)
 311  			arr = append(arr, elem)
 312  			return true
 313  		})
 314  		return arr
 315  	case ObjectValue:
 316  		obj := map[string]interface{}{}
 317  		iter.ReadMapCB(func(Iter *Iterator, field string) bool {
 318  			var elem interface{}
 319  			iter.ReadVal(&elem)
 320  			obj[field] = elem
 321  			return true
 322  		})
 323  		return obj
 324  	default:
 325  		iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
 326  		return nil
 327  	}
 328  }
 329  
 330  // limit maximum depth of nesting, as allowed by https://tools.ietf.org/html/rfc7159#section-9
 331  const maxDepth = 10000
 332  
 333  func (iter *Iterator) incrementDepth() (success bool) {
 334  	iter.depth++
 335  	if iter.depth <= maxDepth {
 336  		return true
 337  	}
 338  	iter.ReportError("incrementDepth", "exceeded max depth")
 339  	return false
 340  }
 341  
 342  func (iter *Iterator) decrementDepth() (success bool) {
 343  	iter.depth--
 344  	if iter.depth >= 0 {
 345  		return true
 346  	}
 347  	iter.ReportError("decrementDepth", "unexpected negative nesting")
 348  	return false
 349  }
 350