Skip to content

Commit

Permalink
add ArrayIterator to iterator over array values
Browse files Browse the repository at this point in the history
  • Loading branch information
80avin committed Oct 2, 2022
1 parent 61b32cf commit d1498ac
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions parser.go
Expand Up @@ -19,6 +19,7 @@ var (
OverflowIntegerError = errors.New("Value is number, but overflowed while parsing")
MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
NullValueError = errors.New("Value is null")
DoneError = errors.New("Done. Reached End of Iterator")
)

// How much stack space to allocate for unescaping JSON strings; if a string longer
Expand Down Expand Up @@ -1069,6 +1070,86 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int
return offset, nil
}

func ArrayIterator(data []byte, keys ...string) (next func() ( []bytes, ValueType, int, error), err error) {
err := error(nil)
makeNextError := func(err error) func() ([]bytes, ValueType, int, error) {
return func() ([]bytes, ValueType, int, error) { return nil, NotExist, -1, err }
}

if len(data) == 0 {
return makeNextError(MalformedObjectError), MalformedObjectError
}

nT := nextToken(data)
if nT == -1 {
return makeNextError(MalformedJsonError), MalformedJsonError
}

offset = nT + 1

if len(keys) > 0 {
if offset = searchKeys(data, keys...); offset == -1 {
return makeNextError(KeyPathNotFoundError), KeyPathNotFoundError
}

// Go to closest value
nO := nextToken(data[offset:])
if nO == -1 {
return makeNextError(MalformedJsonError), MalformedJsonError
}

offset += nO

if data[offset] != '[' {
return makeNextError(MalformedArrayError), MalformedArrayError
}

offset++
}

isFirst, nextOffset := true, offset

next = func() ([]bytes, ValueType, int, error) {
offset = nextOffset

nO := nextToken(data[offset:])
if nO == -1 {
return nil, NotExist, -1, MalformedJsonError
}
offset += nO
if data[offset] == ']' {
return nil, NotExist, -1, DoneError
}

if !isFirst && data[offset] != ',' {
return nil, NotExist, -1, MalformedArrayError
}
if !isFirst {
offset++
}

v, t, o, e := Get(data[offset:])

if e != nil {
return nil, NotExist, -1, e
}

if o == 0 {
return nil, NotExist, -1, DoneError
}

if t == NotExist {
return nil, NotExist, -1, DoneError
}

isFirst = false
nextOffset = offset + o

return v, t, offset - len(v), e
}
return next, nil
}

// ObjectEach iterates over the key-value pairs of a JSON object, invoking a given callback for each such entry
func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) {
offset := 0
Expand Down

0 comments on commit d1498ac

Please sign in to comment.