SYS-REQ-115
(config Config, data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string)
| 1907 | |
| 1908 | // SYS-REQ-115 |
| 1909 | func objectEachConfig(config Config, data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) { |
| 1910 | offset := 0 |
| 1911 | |
| 1912 | // Descend to the desired key, if requested |
| 1913 | if len(keys) > 0 { |
| 1914 | if off := searchKeysConfig(config, data, keys...); off == -1 { |
| 1915 | return KeyPathNotFoundError |
| 1916 | } else { |
| 1917 | offset = off |
| 1918 | } |
| 1919 | } |
| 1920 | |
| 1921 | // Validate and skip past opening brace |
| 1922 | if off := nextTokenConfig(config, data[offset:]); off == -1 { |
| 1923 | return MalformedObjectError |
| 1924 | } else if offset += off; data[offset] != '{' { |
| 1925 | return MalformedObjectError |
| 1926 | } else { |
| 1927 | offset++ |
| 1928 | } |
| 1929 | |
| 1930 | // Skip to the first token inside the object, or stop if we find the ending brace |
| 1931 | if off := nextTokenConfig(config, data[offset:]); off == -1 { |
| 1932 | return MalformedJsonError |
| 1933 | } else if offset += off; data[offset] == '}' { |
| 1934 | return nil |
| 1935 | } |
| 1936 | |
| 1937 | // Loop pre-condition: data[offset] points to what should be either the next entry's key, |
| 1938 | // or the closing brace (if it's anything else, the JSON is malformed). |
| 1939 | // Every iteration either returns or advances offset past a token, so the loop |
| 1940 | // always exits via return; the former `offset < len(data)` guard was structurally |
| 1941 | // always true because internal nextToken/stringEnd calls return errors before |
| 1942 | // offset can reach len(data). |
| 1943 | for { |
| 1944 | // Step 1: find the next key |
| 1945 | var key []byte |
| 1946 | |
| 1947 | // Check what the the next token is: start of string, end of object, or something else (error) |
| 1948 | switch data[offset] { |
| 1949 | case '"': |
| 1950 | offset++ // accept as string and skip opening quote |
| 1951 | case '\'': |
| 1952 | if !config.AllowSingleQuotes { |
| 1953 | return MalformedObjectError |
| 1954 | } |
| 1955 | offset++ // accept as string and skip opening quote |
| 1956 | case '}': |
| 1957 | return nil // we found the end of the object; stop and return success |
| 1958 | default: |
| 1959 | return MalformedObjectError |
| 1960 | } |
| 1961 | |
| 1962 | // Find the end of the key string |
| 1963 | var keyEscaped bool |
| 1964 | quote := data[offset-1] |
| 1965 | if off, esc := stringEndConfig(config, data[offset:], quote); off == -1 { |
| 1966 | return MalformedJsonError |
no test coverage detected