gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

iter.go (7897B)


      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 }