1package jsoniter 2 3import ( 4 "encoding/json" 5 "fmt" 6 "io" 7) 8 9// ValueType the type for JSON element 10type ValueType int 11 12const ( 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 29var hexDigits []byte 30var valueTypes []ValueType 31 32func 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. 71type 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 85func 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 97func 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 109func 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 121func 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 126func (iter *Iterator) Pool() IteratorPool { 127 return iter.cfg 128} 129 130// Reset reuse iterator instance by specifying another reader 131func (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 140func (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 150func (iter *Iterator) WhatIsNext() ValueType { 151 valueType := valueTypes[iter.nextToken()] 152 iter.unreadByte() 153 return valueType 154} 155 156func (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 169func (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 181func (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. 200func (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 229func (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 238func (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 252func (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 282func (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{}. 291func (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 331const maxDepth = 10000 332 333func (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 342func (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