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)
| 801 | // iteration by returning an error. io.EOF stops iteration gracefully. |
| 802 | // SYS-REQ-008 |
| 803 | func EachKeyErr(data []byte, cb func(idx int, value []byte, vt ValueType, err error) error, paths ...[]string) error { |
| 804 | var x struct{} |
| 805 | var level, pathsMatched, i int |
| 806 | ln := len(data) |
| 807 | |
| 808 | pathFlags := make([]bool, stackArraySize)[:] |
| 809 | if len(paths) > cap(pathFlags) { |
| 810 | pathFlags = make([]bool, len(paths))[:] |
| 811 | } |
| 812 | pathFlags = pathFlags[0:len(paths)] |
| 813 | |
| 814 | var maxPath int |
| 815 | for _, p := range paths { |
| 816 | if len(p) > maxPath { |
| 817 | maxPath = len(p) |
| 818 | } |
| 819 | } |
| 820 | |
| 821 | pathsBuf := make([]string, stackArraySize)[:] |
| 822 | if maxPath > cap(pathsBuf) { |
| 823 | pathsBuf = make([]string, maxPath)[:] |
| 824 | } |
| 825 | pathsBuf = pathsBuf[0:maxPath] |
| 826 | |
| 827 | for i < ln { |
| 828 | switch data[i] { |
| 829 | case '"': |
| 830 | i++ |
| 831 | keyBegin := i |
| 832 | |
| 833 | strEnd, keyEscaped := stringEnd(data[i:]) |
| 834 | if strEnd == -1 { |
| 835 | return nil |
| 836 | } |
| 837 | i += strEnd |
| 838 | |
| 839 | keyEnd := i - 1 |
| 840 | |
| 841 | valueOffset := nextToken(data[i:]) |
| 842 | if valueOffset == -1 { |
| 843 | return nil |
| 844 | } |
| 845 | |
| 846 | i += valueOffset |
| 847 | |
| 848 | if data[i] == ':' { |
| 849 | match := -1 |
| 850 | key := data[keyBegin:keyEnd] |
| 851 | |
| 852 | var keyUnesc []byte |
| 853 | if !keyEscaped { |
| 854 | keyUnesc = key |
| 855 | } else { |
| 856 | var stackbuf [unescapeStackBufSize]byte |
| 857 | if ku, unescapeErr := Unescape(key, stackbuf[:]); unescapeErr != nil { |
| 858 | return nil |
| 859 | } else { |
| 860 | keyUnesc = ku |