SYS-REQ-008, SYS-REQ-085, SYS-REQ-111
(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string)
| 529 | |
| 530 | // SYS-REQ-008, SYS-REQ-085, SYS-REQ-111 |
| 531 | func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string) int { |
| 532 | var x struct{} |
| 533 | var level, pathsMatched, i int |
| 534 | ln := len(data) |
| 535 | |
| 536 | pathFlags := make([]bool, stackArraySize)[:] |
| 537 | if len(paths) > cap(pathFlags) { |
| 538 | pathFlags = make([]bool, len(paths))[:] |
| 539 | } |
| 540 | pathFlags = pathFlags[0:len(paths)] |
| 541 | |
| 542 | var maxPath int |
| 543 | for _, p := range paths { |
| 544 | if len(p) > maxPath { |
| 545 | maxPath = len(p) |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | pathsBuf := make([]string, stackArraySize)[:] |
| 550 | if maxPath > cap(pathsBuf) { |
| 551 | pathsBuf = make([]string, maxPath)[:] |
| 552 | } |
| 553 | pathsBuf = pathsBuf[0:maxPath] |
| 554 | |
| 555 | for i < ln { |
| 556 | switch data[i] { |
| 557 | case '"': |
| 558 | i++ |
| 559 | keyBegin := i |
| 560 | |
| 561 | strEnd, keyEscaped := stringEnd(data[i:]) |
| 562 | if strEnd == -1 { |
| 563 | return -1 |
| 564 | } |
| 565 | i += strEnd |
| 566 | |
| 567 | keyEnd := i - 1 |
| 568 | |
| 569 | valueOffset := nextToken(data[i:]) |
| 570 | if valueOffset == -1 { |
| 571 | return -1 |
| 572 | } |
| 573 | |
| 574 | i += valueOffset |
| 575 | |
| 576 | // if string is a key, and key level match |
| 577 | if data[i] == ':' { |
| 578 | match := -1 |
| 579 | key := data[keyBegin:keyEnd] |
| 580 | |
| 581 | // for unescape: if there are no escape sequences, this is cheap; if there are, it is a |
| 582 | // bit more expensive, but causes no allocations unless len(key) > unescapeStackBufSize |
| 583 | var keyUnesc []byte |
| 584 | if !keyEscaped { |
| 585 | keyUnesc = key |
| 586 | } else { |
| 587 | var stackbuf [unescapeStackBufSize]byte |
| 588 | if ku, err := Unescape(key, stackbuf[:]); err != nil { |