EachKeyErr finds the requested paths and allows the callback to stop iteration by returning an error. io.EOF stops iteration gracefully. SYS-REQ-008
(data []byte, cb func(idx int, value []byte, vt ValueType, err error) error, paths ...[]string)
| 745 | // iteration by returning an error. io.EOF stops iteration gracefully. |
| 746 | // SYS-REQ-008 |
| 747 | func EachKeyErr(data []byte, cb func(idx int, value []byte, vt ValueType, err error) error, paths ...[]string) error { |
| 748 | var x struct{} |
| 749 | var level, pathsMatched, i int |
| 750 | ln := len(data) |
| 751 | |
| 752 | pathFlags := make([]bool, stackArraySize)[:] |
| 753 | if len(paths) > cap(pathFlags) { |
| 754 | pathFlags = make([]bool, len(paths))[:] |
| 755 | } |
| 756 | pathFlags = pathFlags[0:len(paths)] |
| 757 | |
| 758 | var maxPath int |
| 759 | for _, p := range paths { |
| 760 | if len(p) > maxPath { |
| 761 | maxPath = len(p) |
| 762 | } |
| 763 | } |
| 764 | |
| 765 | pathsBuf := make([]string, stackArraySize)[:] |
| 766 | if maxPath > cap(pathsBuf) { |
| 767 | pathsBuf = make([]string, maxPath)[:] |
| 768 | } |
| 769 | pathsBuf = pathsBuf[0:maxPath] |
| 770 | |
| 771 | for i < ln { |
| 772 | switch data[i] { |
| 773 | case '"': |
| 774 | i++ |
| 775 | keyBegin := i |
| 776 | |
| 777 | strEnd, keyEscaped := stringEnd(data[i:]) |
| 778 | if strEnd == -1 { |
| 779 | return nil |
| 780 | } |
| 781 | i += strEnd |
| 782 | |
| 783 | keyEnd := i - 1 |
| 784 | |
| 785 | valueOffset := nextToken(data[i:]) |
| 786 | if valueOffset == -1 { |
| 787 | return nil |
| 788 | } |
| 789 | |
| 790 | i += valueOffset |
| 791 | |
| 792 | if data[i] == ':' { |
| 793 | match := -1 |
| 794 | key := data[keyBegin:keyEnd] |
| 795 | |
| 796 | var keyUnesc []byte |
| 797 | if !keyEscaped { |
| 798 | keyUnesc = key |
| 799 | } else { |
| 800 | var stackbuf [unescapeStackBufSize]byte |
| 801 | if ku, unescapeErr := Unescape(key, stackbuf[:]); unescapeErr != nil { |
| 802 | return nil |
| 803 | } else { |
| 804 | keyUnesc = ku |