github.com/3JoB/go-json@v0.10.4/internal/decoder/stream.go (about) 1 package decoder 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "strconv" 8 "unsafe" 9 10 "github.com/3JoB/go-json/internal/errors" 11 "github.com/3JoB/unsafeConvert" 12 ) 13 14 const ( 15 initBufSize = 512 16 ) 17 18 type Stream struct { 19 r io.Reader 20 buf []byte 21 bufSize int64 22 length int64 23 offset int64 24 cursor int64 25 filledBuffer bool 26 allRead bool 27 UseNumber bool 28 DisallowUnknownFields bool 29 Option *Option 30 } 31 32 func NewStream(r io.Reader) *Stream { 33 return &Stream{ 34 r: r, 35 bufSize: initBufSize, 36 buf: make([]byte, initBufSize), 37 Option: &Option{}, 38 } 39 } 40 41 func (s *Stream) TotalOffset() int64 { 42 return s.totalOffset() 43 } 44 45 func (s *Stream) Buffered() io.Reader { 46 buflen := int64(len(s.buf)) 47 for i := s.cursor; i < buflen; i++ { 48 if s.buf[i] == nul { 49 return bytes.NewReader(s.buf[s.cursor:i]) 50 } 51 } 52 return bytes.NewReader(s.buf[s.cursor:]) 53 } 54 55 func (s *Stream) PrepareForDecode() error { 56 for { 57 switch s.char() { 58 case ' ', '\t', '\r', '\n': 59 s.cursor++ 60 continue 61 case ',', ':': 62 s.cursor++ 63 return nil 64 case nul: 65 if s.read() { 66 continue 67 } 68 return io.EOF 69 } 70 break 71 } 72 return nil 73 } 74 75 func (s *Stream) totalOffset() int64 { 76 return s.offset + s.cursor 77 } 78 79 func (s *Stream) char() byte { 80 return s.buf[s.cursor] 81 } 82 83 func (s *Stream) equalChar(c byte) bool { 84 cur := s.buf[s.cursor] 85 if cur == nul { 86 s.read() 87 cur = s.buf[s.cursor] 88 } 89 return cur == c 90 } 91 92 func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) { 93 return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data 94 } 95 96 func (s *Stream) bufptr() unsafe.Pointer { 97 return (*sliceHeader)(unsafe.Pointer(&s.buf)).data 98 } 99 100 func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) { 101 s.cursor-- // for retry ( because caller progress cursor position in each loop ) 102 return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data 103 } 104 105 func (s *Stream) Reset() { 106 s.reset() 107 } 108 109 func (s *Stream) More() bool { 110 for { 111 switch s.char() { 112 case ' ', '\n', '\r', '\t': 113 s.cursor++ 114 continue 115 case '}', ']': 116 return false 117 case nul: 118 if s.read() { 119 continue 120 } 121 return false 122 } 123 break 124 } 125 return true 126 } 127 128 func (s *Stream) Token() (any, error) { 129 for { 130 c := s.char() 131 switch c { 132 case ' ', '\n', '\r', '\t': 133 s.cursor++ 134 case '{', '[', ']', '}': 135 s.cursor++ 136 return json.Delim(c), nil 137 case ',', ':': 138 s.cursor++ 139 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 140 bytes := floatBytes(s) 141 str := *(*string)(unsafe.Pointer(&bytes)) 142 if s.UseNumber { 143 return json.Number(str), nil 144 } 145 f64, err := strconv.ParseFloat(str, 64) 146 if err != nil { 147 return nil, err 148 } 149 return f64, nil 150 case '"': 151 bytes, cursor, err := stringBytes(s) 152 s.cursor = cursor 153 if err != nil { 154 return nil, err 155 } 156 return unsafeConvert.StringReflect(bytes), nil 157 case 't': 158 if err := trueBytes(s); err != nil { 159 return nil, err 160 } 161 return true, nil 162 case 'f': 163 if err := falseBytes(s); err != nil { 164 return nil, err 165 } 166 return false, nil 167 case 'n': 168 if err := nullBytes(s); err != nil { 169 return nil, err 170 } 171 return nil, nil 172 case nul: 173 if s.read() { 174 continue 175 } 176 goto END 177 default: 178 return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset()) 179 } 180 } 181 END: 182 return nil, io.EOF 183 } 184 185 func (s *Stream) reset() { 186 s.offset += s.cursor 187 s.buf = s.buf[s.cursor:] 188 s.length -= s.cursor 189 s.cursor = 0 190 } 191 192 func (s *Stream) readBuf() []byte { 193 if s.filledBuffer { 194 s.bufSize *= 2 195 remainBuf := s.buf 196 s.buf = make([]byte, s.bufSize) 197 copy(s.buf, remainBuf) 198 } 199 return s.buf[s.length:] 200 } 201 202 func (s *Stream) read() bool { 203 if s.allRead { 204 return false 205 } 206 buf := s.readBuf() 207 last := len(buf) - 1 208 n, err := s.r.Read(buf[:last]) 209 buf[n] = nul 210 s.length += int64(n) 211 if n == last { 212 s.filledBuffer = true 213 } else { 214 s.filledBuffer = false 215 } 216 if err == io.EOF { 217 s.allRead = true 218 } else if err != nil { 219 return false 220 } 221 return true 222 } 223 224 // form: https://github.com/goccy/go-json/pull/446 225 func (s *Stream) requires(cursor, n int64) (read int) { 226 RETRY: 227 if s.length-cursor < n { 228 if !s.read() { 229 return -1 230 } 231 read++ 232 goto RETRY 233 } 234 return 235 } 236 237 // form: https://github.com/goccy/go-json/pull/446 238 func (s *Stream) syncBufptr(r int, p *unsafe.Pointer) int { 239 if r > 0 { 240 *p = s.bufptr() 241 } 242 return r 243 } 244 245 func (s *Stream) skipWhiteSpace() byte { 246 p := s.bufptr() 247 LOOP: 248 c := char(p, s.cursor) 249 switch c { 250 case ' ', '\n', '\t', '\r': 251 s.cursor++ 252 goto LOOP 253 case nul: 254 if s.read() { 255 p = s.bufptr() 256 goto LOOP 257 } 258 } 259 return c 260 } 261 262 func (s *Stream) skipObject(depth int64) error { 263 braceCount := 1 264 _, cursor, p := s.stat() 265 for { 266 switch char(p, cursor) { 267 case '{': 268 braceCount++ 269 depth++ 270 if depth > maxDecodeNestingDepth { 271 return errors.ErrExceededMaxDepth(s.char(), s.cursor) 272 } 273 case '}': 274 braceCount-- 275 depth-- 276 if braceCount == 0 { 277 s.cursor = cursor + 1 278 return nil 279 } 280 case '[': 281 depth++ 282 if depth > maxDecodeNestingDepth { 283 return errors.ErrExceededMaxDepth(s.char(), s.cursor) 284 } 285 case ']': 286 depth-- 287 case '"': 288 for { 289 cursor++ 290 switch char(p, cursor) { 291 case '\\': 292 cursor++ 293 if char(p, cursor) == nul { 294 s.cursor = cursor 295 if s.read() { 296 _, cursor, p = s.stat() 297 continue 298 } 299 return errors.ErrUnexpectedEndOfJSON("string of object", cursor) 300 } 301 case '"': 302 goto SWITCH_OUT 303 case nul: 304 s.cursor = cursor 305 if s.read() { 306 _, cursor, p = s.statForRetry() 307 continue 308 } 309 return errors.ErrUnexpectedEndOfJSON("string of object", cursor) 310 } 311 } 312 case nul: 313 s.cursor = cursor 314 if s.read() { 315 _, cursor, p = s.stat() 316 continue 317 } 318 return errors.ErrUnexpectedEndOfJSON("object of object", cursor) 319 } 320 SWITCH_OUT: 321 cursor++ 322 } 323 } 324 325 func (s *Stream) skipArray(depth int64) error { 326 bracketCount := 1 327 _, cursor, p := s.stat() 328 for { 329 switch char(p, cursor) { 330 case '[': 331 bracketCount++ 332 depth++ 333 if depth > maxDecodeNestingDepth { 334 return errors.ErrExceededMaxDepth(s.char(), s.cursor) 335 } 336 case ']': 337 bracketCount-- 338 depth-- 339 if bracketCount == 0 { 340 s.cursor = cursor + 1 341 return nil 342 } 343 case '{': 344 depth++ 345 if depth > maxDecodeNestingDepth { 346 return errors.ErrExceededMaxDepth(s.char(), s.cursor) 347 } 348 case '}': 349 depth-- 350 case '"': 351 for { 352 cursor++ 353 switch char(p, cursor) { 354 case '\\': 355 cursor++ 356 if char(p, cursor) == nul { 357 s.cursor = cursor 358 if s.read() { 359 _, cursor, p = s.stat() 360 continue 361 } 362 return errors.ErrUnexpectedEndOfJSON("string of object", cursor) 363 } 364 case '"': 365 goto SWITCH_OUT 366 case nul: 367 s.cursor = cursor 368 if s.read() { 369 _, cursor, p = s.statForRetry() 370 continue 371 } 372 return errors.ErrUnexpectedEndOfJSON("string of object", cursor) 373 } 374 } 375 case nul: 376 s.cursor = cursor 377 if s.read() { 378 _, cursor, p = s.stat() 379 continue 380 } 381 return errors.ErrUnexpectedEndOfJSON("array of object", cursor) 382 } 383 SWITCH_OUT: 384 cursor++ 385 } 386 } 387 388 func (s *Stream) SkipErrorValue() { 389 _ = s.skipValue(0) 390 } 391 392 func (s *Stream) skipValue(depth int64) error { 393 _, cursor, p := s.stat() 394 for { 395 switch char(p, cursor) { 396 case ' ', '\n', '\t', '\r': 397 cursor++ 398 continue 399 case nul: 400 s.cursor = cursor 401 if s.read() { 402 _, cursor, p = s.stat() 403 continue 404 } 405 return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset()) 406 case '{': 407 s.cursor = cursor + 1 408 return s.skipObject(depth + 1) 409 case '[': 410 s.cursor = cursor + 1 411 return s.skipArray(depth + 1) 412 case '"': 413 for { 414 cursor++ 415 switch char(p, cursor) { 416 case '\\': 417 cursor++ 418 if char(p, cursor) == nul { 419 s.cursor = cursor 420 if s.read() { 421 _, cursor, p = s.stat() 422 continue 423 } 424 return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) 425 } 426 case '"': 427 s.cursor = cursor + 1 428 return nil 429 case nul: 430 s.cursor = cursor 431 if s.read() { 432 _, cursor, p = s.statForRetry() 433 continue 434 } 435 return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) 436 } 437 } 438 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 439 for { 440 cursor++ 441 c := char(p, cursor) 442 if floatTable[c] { 443 continue 444 } else if c == nul { 445 if s.read() { 446 _, cursor, p = s.stat() 447 continue 448 } 449 } 450 s.cursor = cursor 451 return nil 452 } 453 case 't': 454 s.cursor = cursor 455 if err := trueBytes(s); err != nil { 456 return err 457 } 458 return nil 459 case 'f': 460 s.cursor = cursor 461 if err := falseBytes(s); err != nil { 462 return err 463 } 464 return nil 465 case 'n': 466 s.cursor = cursor 467 if err := nullBytes(s); err != nil { 468 return err 469 } 470 return nil 471 } 472 cursor++ 473 } 474 } 475 476 func nullBytes(s *Stream) error { 477 if s.requires(s.cursor, 4) < 0 { 478 s.cursor = s.length 479 return errors.ErrUnexpectedEndOfJSON("null", s.cursor) 480 } 481 // current cursor's character is 'n' 482 s.cursor++ 483 if s.char() != 'u' { 484 return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset()) 485 } 486 s.cursor++ 487 if s.char() != 'l' { 488 return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset()) 489 } 490 s.cursor++ 491 if s.char() != 'l' { 492 return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset()) 493 } 494 s.cursor++ 495 return nil 496 } 497 498 func trueBytes(s *Stream) error { 499 if s.requires(s.cursor, 4) < 0 { 500 s.cursor = s.length 501 return errors.ErrUnexpectedEndOfJSON("bool(true)", s.cursor) 502 } 503 // current cursor's character is 't' 504 s.cursor++ 505 if s.char() != 'r' { 506 return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) 507 } 508 s.cursor++ 509 if s.char() != 'u' { 510 return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) 511 } 512 s.cursor++ 513 if s.char() != 'e' { 514 return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) 515 } 516 s.cursor++ 517 return nil 518 } 519 520 func falseBytes(s *Stream) error { 521 if s.requires(s.cursor, 5) < 0 { 522 s.cursor = s.length 523 return errors.ErrUnexpectedEndOfJSON("bool(false)", s.cursor) 524 } 525 // current cursor's character is 'f' 526 s.cursor++ 527 if s.char() != 'a' { 528 return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) 529 } 530 s.cursor++ 531 if s.char() != 'l' { 532 return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) 533 } 534 s.cursor++ 535 if s.char() != 's' { 536 return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) 537 } 538 s.cursor++ 539 if s.char() != 'e' { 540 return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) 541 } 542 s.cursor++ 543 return nil 544 }