Skip to content

Commit d1498ac

Browse files
authored
add ArrayIterator to iterator over array values
1 parent 61b32cf commit d1498ac

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

parser.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var (
1919
OverflowIntegerError = errors.New("Value is number, but overflowed while parsing")
2020
MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
2121
NullValueError = errors.New("Value is null")
22+
DoneError = errors.New("Done. Reached End of Iterator")
2223
)
2324

2425
// 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
10691070
return offset, nil
10701071
}
10711072

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+
10721153
// ObjectEach iterates over the key-value pairs of a JSON object, invoking a given callback for each such entry
10731154
func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) {
10741155
offset := 0

0 commit comments

Comments
 (0)