cloudflared-mirror/vendor/github.com/francoispqt/gojay/decode_object.go

408 lines
9.9 KiB
Go

package gojay
import (
"reflect"
"unsafe"
)
// DecodeObject reads the next JSON-encoded value from the decoder's input (io.Reader) and stores it in the value pointed to by v.
//
// v must implement UnmarshalerJSONObject.
//
// See the documentation for Unmarshal for details about the conversion of JSON into a Go value.
func (dec *Decoder) DecodeObject(j UnmarshalerJSONObject) error {
if dec.isPooled == 1 {
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
}
_, err := dec.decodeObject(j)
return err
}
func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
keys := j.NKeys()
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
case ' ', '\n', '\t', '\r', ',':
case '{':
dec.cursor = dec.cursor + 1
// if keys is zero we will parse all keys
// we run two loops for micro optimization
if keys == 0 {
for dec.cursor < dec.length || dec.read() {
k, done, err := dec.nextKey()
if err != nil {
return 0, err
} else if done {
return dec.cursor, nil
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
if err != nil {
return 0, err
}
} else {
dec.keysDone++
}
dec.called &= 0
}
} else {
for (dec.cursor < dec.length || dec.read()) && dec.keysDone < keys {
k, done, err := dec.nextKey()
if err != nil {
return 0, err
} else if done {
return dec.cursor, nil
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
if err != nil {
return 0, err
}
} else {
dec.keysDone++
}
dec.called &= 0
}
}
// will get to that point when keysDone is not lower than keys anymore
// in that case, we make sure cursor goes to the end of object, but we skip
// unmarshalling
if dec.child&1 != 0 {
end, err := dec.skipObject()
dec.cursor = end
return dec.cursor, err
}
return dec.cursor, nil
case 'n':
dec.cursor++
err := dec.assertNull()
if err != nil {
return 0, err
}
return dec.cursor, nil
default:
// can't unmarshal to struct
dec.err = dec.makeInvalidUnmarshalErr(j)
err := dec.skipData()
if err != nil {
return 0, err
}
return dec.cursor, nil
}
}
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) decodeObjectNull(v interface{}) (int, error) {
// make sure the value is a pointer
vv := reflect.ValueOf(v)
vvt := vv.Type()
if vvt.Kind() != reflect.Ptr || vvt.Elem().Kind() != reflect.Ptr {
dec.err = ErrUnmarshalPtrExpected
return 0, dec.err
}
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
case ' ', '\n', '\t', '\r', ',':
case '{':
elt := vv.Elem()
n := reflect.New(elt.Type().Elem())
elt.Set(n)
var j UnmarshalerJSONObject
var ok bool
if j, ok = n.Interface().(UnmarshalerJSONObject); !ok {
dec.err = dec.makeInvalidUnmarshalErr((UnmarshalerJSONObject)(nil))
return 0, dec.err
}
keys := j.NKeys()
dec.cursor = dec.cursor + 1
// if keys is zero we will parse all keys
// we run two loops for micro optimization
if keys == 0 {
for dec.cursor < dec.length || dec.read() {
k, done, err := dec.nextKey()
if err != nil {
return 0, err
} else if done {
return dec.cursor, nil
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
if err != nil {
return 0, err
}
} else {
dec.keysDone++
}
dec.called &= 0
}
} else {
for (dec.cursor < dec.length || dec.read()) && dec.keysDone < keys {
k, done, err := dec.nextKey()
if err != nil {
return 0, err
} else if done {
return dec.cursor, nil
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
if err != nil {
return 0, err
}
} else {
dec.keysDone++
}
dec.called &= 0
}
}
// will get to that point when keysDone is not lower than keys anymore
// in that case, we make sure cursor goes to the end of object, but we skip
// unmarshalling
if dec.child&1 != 0 {
end, err := dec.skipObject()
dec.cursor = end
return dec.cursor, err
}
return dec.cursor, nil
case 'n':
dec.cursor++
err := dec.assertNull()
if err != nil {
return 0, err
}
return dec.cursor, nil
default:
// can't unmarshal to struct
dec.err = dec.makeInvalidUnmarshalErr((UnmarshalerJSONObject)(nil))
err := dec.skipData()
if err != nil {
return 0, err
}
return dec.cursor, nil
}
}
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipObject() (int, error) {
var objectsOpen = 1
var objectsClosed = 0
for j := dec.cursor; j < dec.length || dec.read(); j++ {
switch dec.data[j] {
case '}':
objectsClosed++
// everything is closed return
if objectsOpen == objectsClosed {
// add char to object data
return j + 1, nil
}
case '{':
objectsOpen++
case '"':
j++
var isInEscapeSeq bool
var isFirstQuote = true
for ; j < dec.length || dec.read(); j++ {
if dec.data[j] != '"' {
continue
}
if dec.data[j-1] != '\\' || (!isInEscapeSeq && !isFirstQuote) {
break
} else {
isInEscapeSeq = false
}
if isFirstQuote {
isFirstQuote = false
}
// loop backward and count how many anti slash found
// to see if string is effectively escaped
ct := 0
for i := j - 1; i > 0; i-- {
if dec.data[i] != '\\' {
break
}
ct++
}
// is pair number of slashes, quote is not escaped
if ct&1 == 0 {
break
}
isInEscapeSeq = true
}
default:
continue
}
}
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) nextKey() (string, bool, error) {
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
case ' ', '\n', '\t', '\r', ',':
continue
case '"':
dec.cursor = dec.cursor + 1
start, end, err := dec.getString()
if err != nil {
return "", false, err
}
var found byte
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
if dec.data[dec.cursor] == ':' {
found |= 1
break
}
}
if found&1 != 0 {
dec.cursor++
d := dec.data[start : end-1]
return *(*string)(unsafe.Pointer(&d)), false, nil
}
return "", false, dec.raiseInvalidJSONErr(dec.cursor)
case '}':
dec.cursor = dec.cursor + 1
return "", true, nil
default:
// can't unmarshall to struct
return "", false, dec.raiseInvalidJSONErr(dec.cursor)
}
}
return "", false, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipData() error {
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
case ' ', '\n', '\t', '\r', ',':
continue
// is null
case 'n':
dec.cursor++
err := dec.assertNull()
if err != nil {
return err
}
return nil
case 't':
dec.cursor++
err := dec.assertTrue()
if err != nil {
return err
}
return nil
// is false
case 'f':
dec.cursor++
err := dec.assertFalse()
if err != nil {
return err
}
return nil
// is an object
case '{':
dec.cursor = dec.cursor + 1
end, err := dec.skipObject()
dec.cursor = end
return err
// is string
case '"':
dec.cursor = dec.cursor + 1
err := dec.skipString()
return err
// is array
case '[':
dec.cursor = dec.cursor + 1
end, err := dec.skipArray()
dec.cursor = end
return err
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
end, err := dec.skipNumber()
dec.cursor = end
return err
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
// DecodeObjectFunc is a func type implementing UnmarshalerJSONObject.
// Use it to cast a `func(*Decoder, k string) error` to Unmarshal an object on the fly.
type DecodeObjectFunc func(*Decoder, string) error
// UnmarshalJSONObject implements UnmarshalerJSONObject.
func (f DecodeObjectFunc) UnmarshalJSONObject(dec *Decoder, k string) error {
return f(dec, k)
}
// NKeys implements UnmarshalerJSONObject.
func (f DecodeObjectFunc) NKeys() int {
return 0
}
// Add Values functions
// AddObject decodes the JSON value within an object or an array to a UnmarshalerJSONObject.
func (dec *Decoder) AddObject(v UnmarshalerJSONObject) error {
return dec.Object(v)
}
// AddObjectNull decodes the JSON value within an object or an array to a UnmarshalerJSONObject.
func (dec *Decoder) AddObjectNull(v interface{}) error {
return dec.ObjectNull(v)
}
// Object decodes the JSON value within an object or an array to a UnmarshalerJSONObject.
func (dec *Decoder) Object(value UnmarshalerJSONObject) error {
initialKeysDone := dec.keysDone
initialChild := dec.child
dec.keysDone = 0
dec.called = 0
dec.child |= 1
newCursor, err := dec.decodeObject(value)
if err != nil {
return err
}
dec.cursor = newCursor
dec.keysDone = initialKeysDone
dec.child = initialChild
dec.called |= 1
return nil
}
// ObjectNull decodes the JSON value within an object or an array to a UnmarshalerJSONObject.
// v should be a pointer to an UnmarshalerJSONObject,
// if `null` value is encountered in JSON, it will leave the value v untouched,
// else it will create a new instance of the UnmarshalerJSONObject behind v.
func (dec *Decoder) ObjectNull(v interface{}) error {
initialKeysDone := dec.keysDone
initialChild := dec.child
dec.keysDone = 0
dec.called = 0
dec.child |= 1
newCursor, err := dec.decodeObjectNull(v)
if err != nil {
return err
}
dec.cursor = newCursor
dec.keysDone = initialKeysDone
dec.child = initialChild
dec.called |= 1
return nil
}