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 captureStartedAt int 78 captured []byte 79 Error error 80 Attachment interface{} // open for customized decoder 81} 82 83// NewIterator creates an empty Iterator instance 84func NewIterator(cfg API) *Iterator { 85 return &Iterator{ 86 cfg: cfg.(*frozenConfig), 87 reader: nil, 88 buf: nil, 89 head: 0, 90 tail: 0, 91 } 92} 93 94// Parse creates an Iterator instance from io.Reader 95func Parse(cfg API, reader io.Reader, bufSize int) *Iterator { 96 return &Iterator{ 97 cfg: cfg.(*frozenConfig), 98 reader: reader, 99 buf: make([]byte, bufSize), 100 head: 0, 101 tail: 0, 102 } 103} 104 105// ParseBytes creates an Iterator instance from byte array 106func ParseBytes(cfg API, input []byte) *Iterator { 107 return &Iterator{ 108 cfg: cfg.(*frozenConfig), 109 reader: nil, 110 buf: input, 111 head: 0, 112 tail: len(input), 113 } 114} 115 116// ParseString creates an Iterator instance from string 117func ParseString(cfg API, input string) *Iterator { 118 return ParseBytes(cfg, []byte(input)) 119} 120 121// Pool returns a pool can provide more iterator with same configuration 122func (iter *Iterator) Pool() IteratorPool { 123 return iter.cfg 124} 125 126// Reset reuse iterator instance by specifying another reader 127func (iter *Iterator) Reset(reader io.Reader) *Iterator { 128 iter.reader = reader 129 iter.head = 0 130 iter.tail = 0 131 return iter 132} 133 134// ResetBytes reuse iterator instance by specifying another byte array as input 135func (iter *Iterator) ResetBytes(input []byte) *Iterator { 136 iter.reader = nil 137 iter.buf = input 138 iter.head = 0 139 iter.tail = len(input) 140 return iter 141} 142 143// WhatIsNext gets ValueType of relatively next json element 144func (iter *Iterator) WhatIsNext() ValueType { 145 valueType := valueTypes[iter.nextToken()] 146 iter.unreadByte() 147 return valueType 148} 149 150func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool { 151 for i := iter.head; i < iter.tail; i++ { 152 c := iter.buf[i] 153 switch c { 154 case ' ', '\n', '\t', '\r': 155 continue 156 } 157 iter.head = i 158 return false 159 } 160 return true 161} 162 163func (iter *Iterator) isObjectEnd() bool { 164 c := iter.nextToken() 165 if c == ',' { 166 return false 167 } 168 if c == '}' { 169 return true 170 } 171 iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c})) 172 return true 173} 174 175func (iter *Iterator) nextToken() byte { 176 // a variation of skip whitespaces, returning the next non-whitespace token 177 for { 178 for i := iter.head; i < iter.tail; i++ { 179 c := iter.buf[i] 180 switch c { 181 case ' ', '\n', '\t', '\r': 182 continue 183 } 184 iter.head = i + 1 185 return c 186 } 187 if !iter.loadMore() { 188 return 0 189 } 190 } 191} 192 193// ReportError record a error in iterator instance with current position. 194func (iter *Iterator) ReportError(operation string, msg string) { 195 if iter.Error != nil { 196 if iter.Error != io.EOF { 197 return 198 } 199 } 200 peekStart := iter.head - 10 201 if peekStart < 0 { 202 peekStart = 0 203 } 204 peekEnd := iter.head + 10 205 if peekEnd > iter.tail { 206 peekEnd = iter.tail 207 } 208 parsing := string(iter.buf[peekStart:peekEnd]) 209 contextStart := iter.head - 50 210 if contextStart < 0 { 211 contextStart = 0 212 } 213 contextEnd := iter.head + 50 214 if contextEnd > iter.tail { 215 contextEnd = iter.tail 216 } 217 context := string(iter.buf[contextStart:contextEnd]) 218 iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...", 219 operation, msg, iter.head-peekStart, parsing, context) 220} 221 222// CurrentBuffer gets current buffer as string for debugging purpose 223func (iter *Iterator) CurrentBuffer() string { 224 peekStart := iter.head - 10 225 if peekStart < 0 { 226 peekStart = 0 227 } 228 return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head, 229 string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) 230} 231 232func (iter *Iterator) readByte() (ret byte) { 233 if iter.head == iter.tail { 234 if iter.loadMore() { 235 ret = iter.buf[iter.head] 236 iter.head++ 237 return ret 238 } 239 return 0 240 } 241 ret = iter.buf[iter.head] 242 iter.head++ 243 return ret 244} 245 246func (iter *Iterator) loadMore() bool { 247 if iter.reader == nil { 248 if iter.Error == nil { 249 iter.head = iter.tail 250 iter.Error = io.EOF 251 } 252 return false 253 } 254 if iter.captured != nil { 255 iter.captured = append(iter.captured, 256 iter.buf[iter.captureStartedAt:iter.tail]...) 257 iter.captureStartedAt = 0 258 } 259 for { 260 n, err := iter.reader.Read(iter.buf) 261 if n == 0 { 262 if err != nil { 263 if iter.Error == nil { 264 iter.Error = err 265 } 266 return false 267 } 268 } else { 269 iter.head = 0 270 iter.tail = n 271 return true 272 } 273 } 274} 275 276func (iter *Iterator) unreadByte() { 277 if iter.Error != nil { 278 return 279 } 280 iter.head-- 281 return 282} 283 284// Read read the next JSON element as generic interface{}. 285func (iter *Iterator) Read() interface{} { 286 valueType := iter.WhatIsNext() 287 switch valueType { 288 case StringValue: 289 return iter.ReadString() 290 case NumberValue: 291 if iter.cfg.configBeforeFrozen.UseNumber { 292 return json.Number(iter.readNumberAsString()) 293 } 294 return iter.ReadFloat64() 295 case NilValue: 296 iter.skipFourBytes('n', 'u', 'l', 'l') 297 return nil 298 case BoolValue: 299 return iter.ReadBool() 300 case ArrayValue: 301 arr := []interface{}{} 302 iter.ReadArrayCB(func(iter *Iterator) bool { 303 var elem interface{} 304 iter.ReadVal(&elem) 305 arr = append(arr, elem) 306 return true 307 }) 308 return arr 309 case ObjectValue: 310 obj := map[string]interface{}{} 311 iter.ReadMapCB(func(Iter *Iterator, field string) bool { 312 var elem interface{} 313 iter.ReadVal(&elem) 314 obj[field] = elem 315 return true 316 }) 317 return obj 318 default: 319 iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType)) 320 return nil 321 } 322} 323