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)
| 855 | // iteration by returning an error. io.EOF stops iteration gracefully. |
| 856 | // SYS-REQ-008 |
| 857 | func EachKeyErr(data []byte, cb func(idx int, value []byte, vt ValueType, err error) error, paths ...[]string) error { |
| 858 | var x struct{} |
| 859 | var level, pathsMatched, i int |
| 860 | ln := len(data) |
| 861 | |
| 862 | pathFlags := make([]bool, stackArraySize)[:] |
| 863 | if len(paths) > cap(pathFlags) { |
| 864 | pathFlags = make([]bool, len(paths))[:] |
| 865 | } |
| 866 | pathFlags = pathFlags[0:len(paths)] |
| 867 | |
| 868 | var maxPath int |
| 869 | for _, p := range paths { |
| 870 | if len(p) > maxPath { |
| 871 | maxPath = len(p) |
| 872 | } |
| 873 | } |
| 874 | |
| 875 | pathsBuf := make([]string, stackArraySize)[:] |
| 876 | if maxPath > cap(pathsBuf) { |
| 877 | pathsBuf = make([]string, maxPath)[:] |
| 878 | } |
| 879 | pathsBuf = pathsBuf[0:maxPath] |
| 880 | |
| 881 | for i < ln { |
| 882 | switch data[i] { |
| 883 | case '"': |
| 884 | i++ |
| 885 | keyBegin := i |
| 886 | |
| 887 | strEnd, keyEscaped := stringEnd(data[i:]) |
| 888 | if strEnd == -1 { |
| 889 | return nil |
| 890 | } |
| 891 | i += strEnd |
| 892 | |
| 893 | keyEnd := i - 1 |
| 894 | |
| 895 | valueOffset := nextToken(data[i:]) |
| 896 | if valueOffset == -1 { |
| 897 | return nil |
| 898 | } |
| 899 | |
| 900 | i += valueOffset |
| 901 | |
| 902 | if data[i] == ':' { |
| 903 | match := -1 |
| 904 | key := data[keyBegin:keyEnd] |
| 905 | |
| 906 | var keyUnesc []byte |
| 907 | if !keyEscaped { |
| 908 | keyUnesc = key |
| 909 | } else { |
| 910 | var stackbuf [unescapeStackBufSize]byte |
| 911 | if ku, unescapeErr := Unescape(key, stackbuf[:]); unescapeErr != nil { |
| 912 | return nil |
| 913 | } else { |
| 914 | keyUnesc = ku |