|
19 | 19 | OverflowIntegerError = errors.New("Value is number, but overflowed while parsing")
|
20 | 20 | MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
|
21 | 21 | NullValueError = errors.New("Value is null")
|
| 22 | + DoneError = errors.New("Done. Reached End of Iterator") |
22 | 23 | )
|
23 | 24 |
|
24 | 25 | // How much stack space to allocate for unescaping JSON strings; if a string longer
|
@@ -1069,6 +1070,86 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int
|
1069 | 1070 | return offset, nil
|
1070 | 1071 | }
|
1071 | 1072 |
|
| 1073 | +func ArrayIterator(data []byte, keys ...string) (next func() ( []bytes, ValueType, int, error), err error) { |
| 1074 | + err := error(nil) |
| 1075 | + makeNextError := func(err error) func() ([]bytes, ValueType, int, error) { |
| 1076 | + return func() ([]bytes, ValueType, int, error) { return nil, NotExist, -1, err } |
| 1077 | + } |
| 1078 | + |
| 1079 | + if len(data) == 0 { |
| 1080 | + return makeNextError(MalformedObjectError), MalformedObjectError |
| 1081 | + } |
| 1082 | + |
| 1083 | + nT := nextToken(data) |
| 1084 | + if nT == -1 { |
| 1085 | + return makeNextError(MalformedJsonError), MalformedJsonError |
| 1086 | + } |
| 1087 | + |
| 1088 | + offset = nT + 1 |
| 1089 | + |
| 1090 | + if len(keys) > 0 { |
| 1091 | + if offset = searchKeys(data, keys...); offset == -1 { |
| 1092 | + return makeNextError(KeyPathNotFoundError), KeyPathNotFoundError |
| 1093 | + } |
| 1094 | + |
| 1095 | + // Go to closest value |
| 1096 | + nO := nextToken(data[offset:]) |
| 1097 | + if nO == -1 { |
| 1098 | + return makeNextError(MalformedJsonError), MalformedJsonError |
| 1099 | + } |
| 1100 | + |
| 1101 | + offset += nO |
| 1102 | + |
| 1103 | + if data[offset] != '[' { |
| 1104 | + return makeNextError(MalformedArrayError), MalformedArrayError |
| 1105 | + } |
| 1106 | + |
| 1107 | + offset++ |
| 1108 | + } |
| 1109 | + |
| 1110 | + isFirst, nextOffset := true, offset |
| 1111 | + |
| 1112 | + next = func() ([]bytes, ValueType, int, error) { |
| 1113 | + offset = nextOffset |
| 1114 | + |
| 1115 | + nO := nextToken(data[offset:]) |
| 1116 | + if nO == -1 { |
| 1117 | + return nil, NotExist, -1, MalformedJsonError |
| 1118 | + } |
| 1119 | + offset += nO |
| 1120 | + if data[offset] == ']' { |
| 1121 | + return nil, NotExist, -1, DoneError |
| 1122 | + } |
| 1123 | + |
| 1124 | + if !isFirst && data[offset] != ',' { |
| 1125 | + return nil, NotExist, -1, MalformedArrayError |
| 1126 | + } |
| 1127 | + if !isFirst { |
| 1128 | + offset++ |
| 1129 | + } |
| 1130 | + |
| 1131 | + v, t, o, e := Get(data[offset:]) |
| 1132 | + |
| 1133 | + if e != nil { |
| 1134 | + return nil, NotExist, -1, e |
| 1135 | + } |
| 1136 | + |
| 1137 | + if o == 0 { |
| 1138 | + return nil, NotExist, -1, DoneError |
| 1139 | + } |
| 1140 | + |
| 1141 | + if t == NotExist { |
| 1142 | + return nil, NotExist, -1, DoneError |
| 1143 | + } |
| 1144 | + |
| 1145 | + isFirst = false |
| 1146 | + nextOffset = offset + o |
| 1147 | + |
| 1148 | + return v, t, offset - len(v), e |
| 1149 | + } |
| 1150 | + return next, nil |
| 1151 | +} |
| 1152 | + |
1072 | 1153 | // ObjectEach iterates over the key-value pairs of a JSON object, invoking a given callback for each such entry
|
1073 | 1154 | func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) {
|
1074 | 1155 | offset := 0
|
|
0 commit comments