2021-04-22 17:22:09 +03:00
|
|
|
package jsonpath
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2021-05-07 19:48:57 +03:00
|
|
|
|
2021-09-15 15:01:01 +03:00
|
|
|
json "github.com/nspcc-dev/go-ordered-json"
|
2021-04-22 17:22:09 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
2022-04-20 21:30:09 +03:00
|
|
|
// pathTokenType represents a single JSONPath token.
|
2021-04-22 17:22:09 +03:00
|
|
|
pathTokenType byte
|
|
|
|
|
2022-04-20 21:30:09 +03:00
|
|
|
// pathParser combines a JSONPath and a position to start parsing from.
|
2021-04-22 17:22:09 +03:00
|
|
|
pathParser struct {
|
2021-04-30 10:35:33 +03:00
|
|
|
s string
|
|
|
|
i int
|
|
|
|
depth int
|
2021-04-22 17:22:09 +03:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
pathInvalid pathTokenType = iota
|
|
|
|
pathRoot
|
|
|
|
pathDot
|
|
|
|
pathLeftBracket
|
|
|
|
pathRightBracket
|
|
|
|
pathAsterisk
|
|
|
|
pathComma
|
|
|
|
pathColon
|
|
|
|
pathIdentifier
|
|
|
|
pathString
|
|
|
|
pathNumber
|
|
|
|
)
|
|
|
|
|
2022-02-26 17:02:10 +03:00
|
|
|
const (
|
|
|
|
maxNestingDepth = 6
|
|
|
|
maxObjects = 1024
|
|
|
|
)
|
2021-04-30 10:35:33 +03:00
|
|
|
|
2021-04-22 17:22:09 +03:00
|
|
|
// Get returns substructures of value selected by path.
|
2022-04-20 21:30:09 +03:00
|
|
|
// The result is always non-nil unless the path is invalid.
|
2023-04-03 13:34:24 +03:00
|
|
|
func Get(path string, value any) ([]any, bool) {
|
2021-05-11 12:35:28 +03:00
|
|
|
if path == "" {
|
2023-04-03 13:34:24 +03:00
|
|
|
return []any{value}, true
|
2021-05-11 12:35:28 +03:00
|
|
|
}
|
|
|
|
|
2021-04-30 10:35:33 +03:00
|
|
|
p := pathParser{
|
|
|
|
depth: maxNestingDepth,
|
|
|
|
s: path,
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
|
|
|
|
typ, _ := p.nextToken()
|
|
|
|
if typ != pathRoot {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
objs := []any{value}
|
2021-04-22 17:22:09 +03:00
|
|
|
for p.i < len(p.s) {
|
|
|
|
var ok bool
|
|
|
|
|
|
|
|
switch typ, _ := p.nextToken(); typ {
|
|
|
|
case pathDot:
|
|
|
|
objs, ok = p.processDot(objs)
|
|
|
|
case pathLeftBracket:
|
|
|
|
objs, ok = p.processLeftBracket(objs)
|
*: fix linter exhaustive errors
```
pkg/smartcontract/rpcbinding/binding.go:523:2 exhaustive missing
cases in switch of type smartcontract.ParamType: smartcontract
.UnknownType
pkg/smartcontract/rpcbinding/binding.go:572:2 exhaustive missing
cases in switch of type smartcontract.ParamType: smartcontract
.UnknownType
pkg/smartcontract/rpcbinding/binding.go:862:2 exhaustive missing
cases in switch of type smartcontract.ParamType: smartcontract
.UnknownType, smartcontract.AnyType, smartcontract.BoolType,
smartcontract.IntegerType, smartcontract.ByteArrayType, smartcontract
.Hash160Type, smartcontract.Hash256Type, smartcontract.SignatureType,
smartcontract.InteropInterfaceType, smartcontract.VoidType
pkg/smartcontract/param_type.go:165:2 exhaustive missing
cases in switch of type smartcontract.ParamType: smartcontract
.UnknownType
pkg/smartcontract/manifest/permission.go:103:2 exhaustive missing
cases in switch of type manifest.PermissionType: manifest
.PermissionWildcard
pkg/services/notary/core_test.go:223:4 exhaustive missing
cases in switch of type notary.RequestType: notary.Contract
pkg/services/notary/core_test.go:292:4 exhaustive missing
cases in switch of type notary.RequestType: notary.Contract
pkg/services/oracle/jsonpath/jsonpath.go:62:3 exhaustive missing
cases in switch of type jsonpath.pathTokenType: jsonpath.pathInvalid,
jsonpath.pathRoot, jsonpath.pathRightBracket, jsonpath.pathAsterisk,
jsonpath.pathComma, jsonpath.pathColon, jsonpath.pathIdentifier,
jsonpath.pathString, jsonpath.pathNumber
pkg/services/rpcsrv/server.go:2740:3 exhaustive missing
cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc
.MissedEventID
pkg/services/rpcsrv/server.go:2804:2 exhaustive missing
cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc
.MissedEventID
pkg/services/rpcsrv/server.go:2864:2 exhaustive missing
cases in switch of type neorpc.EventID: neorpc.InvalidEventID, neorpc
.MissedEventID
pkg/vm/contract_checks.go:153:3 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode
.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode
.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode
.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode
.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14,
opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT,
opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.ENDFINALLY, opcode
.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode
.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK,
opcode.SWAP, opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4,
opcode.REVERSEN, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0,
opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode
.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode
.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode
.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1,
opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode
.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2,
opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode
.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3,
opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode
.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4,
opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode
.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode
.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode
.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode
.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD,
opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL,
opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ,
opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT,
opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP,
opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0,
opcode.NEWARRAY, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP,
opcode.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode
.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS,
opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL,
opcode.ABORTMSG, opcode.ASSERTMSG
pkg/vm/vm.go:912:3 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode
.PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode
.PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode
.PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode
.PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13,
opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP,
opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode
.JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL,
opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT,
opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALL, opcode.CALLL,
opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW,
opcode.TRY, opcode.TRYL, opcode.ENDTRY, opcode.ENDTRYL, opcode
.ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP,
opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode
.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode
.REVERSE3, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0, opcode
.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode
.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode.STSFLD1,
opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode.STSFLD5, opcode
.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2,
opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode.LDLOC6, opcode
.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3,
opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode.STLOC, opcode
.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4,
opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode.STARG0, opcode
.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5,
opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode.MEMCPY, opcode
.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode.INVERT, opcode
.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode.NOTEQUAL, opcode
.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.ADD,
opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD, opcode.POW, opcode
.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL, opcode.SHR, opcode
.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode
.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN,
opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode
.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode
.NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode
.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM,
opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE,
opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode
.CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG
pkg/vm/vm.go:1116:4 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode
.PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode
.PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode
.PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode
.PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13,
opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP,
opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode
.JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL,
opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT,
opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALL, opcode.CALLL,
opcode.CALLA, opcode.CALLT, opcode.ABORT, opcode.ASSERT, opcode.THROW,
opcode.TRY, opcode.TRYL, opcode.ENDTRY, opcode.ENDTRYL, opcode
.ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP,
opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode
.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode
.REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode
.INITSLOT, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode
.LDSFLD3, opcode.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD,
opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode
.STSFLD4, opcode.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0,
opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode
.LDLOC5, opcode.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1,
opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode
.STLOC6, opcode.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2,
opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode
.LDARG, opcode.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3,
opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode
.NEWBUFFER, opcode.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT,
opcode.RIGHT, opcode.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode
.EQUAL, opcode.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE,
opcode.INC, opcode.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode
.DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode
.MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode
.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.MIN,
opcode.MAX, opcode.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode
.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode
.NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode
.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM,
opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE,
opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE,
opcode.CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG
pkg/compiler/codegen.go:944:5 exhaustive missing
cases in switch of type smartcontract.ParamType: smartcontract
.UnknownType, smartcontract.AnyType, smartcontract.BoolType,
smartcontract.IntegerType, smartcontract.ByteArrayType, smartcontract
.StringType, smartcontract.PublicKeyType, smartcontract.SignatureType,
smartcontract.ArrayType, smartcontract.MapType, smartcontract
.InteropInterfaceType, smartcontract.VoidType
pkg/compiler/codegen.go:1221:3 exhaustive missing
cases in switch of type token.Token: token.ILLEGAL, token.EOF, token
.COMMENT, token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR,
token.STRING, token.ADD, token.SUB, token.MUL, token.QUO, token.REM,
token.AND, token.OR, token.XOR, token.SHL, token.SHR, token.AND_NOT,
token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN,
token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN, token.LAND,
token.LOR, token.ARROW, token.INC, token.DEC, token.EQL, token.LSS,
token.GTR, token.ASSIGN, token.NOT, token.NEQ, token.LEQ, token.GEQ,
token.DEFINE, token.ELLIPSIS, token.LPAREN, token.LBRACK, token.LBRACE,
token.COMMA, token.PERIOD, token.RPAREN, token.RBRACK, token.RBRACE,
token.SEMICOLON, token.COLON, token.CASE, token.CHAN, token.CONST, token
.DEFAULT, token.DEFER, token.ELSE, token.FALLTHROUGH, token.FOR, token
.FUNC, token.GO, token.GOTO, token.IF, token.IMPORT, token.INTERFACE,
token.MAP, token.PACKAGE, token.RANGE, token.RETURN, token.SELECT, token
.STRUCT, token.SWITCH, token.TYPE, token.VAR, token.TILDE
pkg/compiler/codegen.go:1709:2 exhaustive missing
cases in switch of type token.Token: token.ILLEGAL, token.EOF, token
.COMMENT, token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR,
token.STRING, token.ADD, token.SUB, token.MUL, token.QUO, token.REM,
token.AND, token.OR, token.XOR, token.SHL, token.SHR, token.AND_NOT,
token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN,
token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN, token.LAND,
token.LOR, token.ARROW, token.INC, token.DEC, token.ASSIGN, token.NOT,
token.DEFINE, token.ELLIPSIS, token.LPAREN, token.LBRACK, token.LBRACE,
token.COMMA, token.PERIOD, token.RPAREN, token.RBRACK, token.RBRACE,
token.SEMICOLON, token.COLON, token.BREAK, token.CASE, token.CHAN, token
.CONST, token.CONTINUE, token.DEFAULT, token.DEFER, token.ELSE, token
.FALLTHROUGH, token.FOR, token.FUNC, token.GO, token.GOTO, token.IF,
token.IMPORT, token.INTERFACE, token.MAP, token.PACKAGE, token.RANGE,
token.RETURN, token.SELECT, token.STRUCT, token.SWITCH, token.TYPE,
token.VAR, token.TILDE
pkg/compiler/codegen.go:2353:3 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode
.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode
.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode
.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode
.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14,
opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT,
opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.ENDTRY,
opcode.ENDFINALLY, opcode.RET, opcode.SYSCALL, opcode.DEPTH, opcode
.DROP, opcode.NIP, opcode.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER,
opcode.PICK, opcode.TUCK, opcode.SWAP, opcode.ROT, opcode.ROLL, opcode
.REVERSE3, opcode.REVERSE4, opcode.REVERSEN, opcode.INITSSLOT, opcode
.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode
.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0,
opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode
.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1,
opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode
.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2,
opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode
.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3,
opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode
.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4,
opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode
.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode
.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode
.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode
.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD,
opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL,
opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ,
opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT,
opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP,
opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0, opcode
.NEWARRAY, opcode.NEWARRAYT, opcode.NEWSTRUCT0, opcode.NEWSTRUCT,
opcode.NEWMAP, opcode.SIZE, opcode.HASKEY, opcode.KEYS, opcode.VALUES,
opcode.PICKITEM, opcode.APPEND, opcode.SETITEM, opcode.REVERSEITEMS,
opcode.REMOVE, opcode.CLEARITEMS, opcode.POPITEM, opcode.ISNULL, opcode
.ISTYPE, opcode.CONVERT, opcode.ABORTMSG, opcode.ASSERTMSG
pkg/compiler/codegen.go:2474:3 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHNULL, opcode
.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode.PUSHM1, opcode
.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4, opcode
.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode.PUSH9, opcode
.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13, opcode.PUSH14,
opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.CALLA, opcode.CALLT,
opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.ENDFINALLY, opcode
.RET, opcode.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode
.XDROP, opcode.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK,
opcode.SWAP, opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4,
opcode.REVERSEN, opcode.INITSSLOT, opcode.INITSLOT, opcode.LDSFLD0,
opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode
.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD, opcode.STSFLD0, opcode
.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode
.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0, opcode.LDLOC1,
opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode
.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1, opcode.STLOC2,
opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6, opcode
.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3,
opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode.LDARG, opcode
.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4,
opcode.STARG5, opcode.STARG6, opcode.STARG, opcode.NEWBUFFER, opcode
.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT, opcode.RIGHT, opcode
.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode.EQUAL, opcode
.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode
.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode.DIV, opcode.MOD,
opcode.POW, opcode.SQRT, opcode.MODMUL, opcode.MODPOW, opcode.SHL,
opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode.BOOLOR, opcode.NZ,
opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT, opcode.LE, opcode.GT,
opcode.GE, opcode.MIN, opcode.MAX, opcode.WITHIN, opcode.PACKMAP,
opcode.PACKSTRUCT, opcode.PACK, opcode.UNPACK, opcode.NEWARRAY0,
opcode.NEWARRAY, opcode.NEWARRAYT, opcode.NEWSTRUCT0, opcode
.NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode.HASKEY, opcode.KEYS,
opcode.VALUES, opcode.PICKITEM, opcode.APPEND, opcode.SETITEM,
opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS, opcode
.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode.CONVERT, opcode
.ABORTMSG, opcode.ASSERTMSG
pkg/compiler/inline_test.go:34:3 exhaustive missing
cases in switch of type opcode.Opcode: opcode.PUSHINT8, opcode
.PUSHINT16, opcode.PUSHINT32, opcode.PUSHINT64, opcode.PUSHINT128,
opcode.PUSHINT256, opcode.PUSHT, opcode.PUSHF, opcode.PUSHA, opcode
.PUSHNULL, opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4, opcode
.PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode
.PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8, opcode
.PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12, opcode.PUSH13,
opcode.PUSH14, opcode.PUSH15, opcode.PUSH16, opcode.NOP, opcode.JMP,
opcode.JMPL, opcode.JMPIF, opcode.JMPIFL, opcode.JMPIFNOT, opcode
.JMPIFNOTL, opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL,
opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT,
opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL, opcode.CALLA, opcode.CALLT,
opcode.ABORT, opcode.ASSERT, opcode.THROW, opcode.TRY, opcode.TRYL,
opcode.ENDTRY, opcode.ENDTRYL, opcode.ENDFINALLY, opcode.RET, opcode
.SYSCALL, opcode.DEPTH, opcode.DROP, opcode.NIP, opcode.XDROP, opcode
.CLEAR, opcode.DUP, opcode.OVER, opcode.PICK, opcode.TUCK, opcode.SWAP,
opcode.ROT, opcode.ROLL, opcode.REVERSE3, opcode.REVERSE4, opcode
.REVERSEN, opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode
.LDSFLD3, opcode.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6, opcode.LDSFLD,
opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode
.STSFLD4, opcode.STSFLD5, opcode.STSFLD6, opcode.STSFLD, opcode.LDLOC0,
opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode
.LDLOC5, opcode.LDLOC6, opcode.LDLOC, opcode.STLOC0, opcode.STLOC1,
opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode
.STLOC6, opcode.STLOC, opcode.LDARG0, opcode.LDARG1, opcode.LDARG2,
opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6, opcode
.LDARG, opcode.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3,
opcode.STARG4, opcode.STARG5, opcode.STARG6, opcode.STARG, opcode
.NEWBUFFER, opcode.MEMCPY, opcode.CAT, opcode.SUBSTR, opcode.LEFT,
opcode.RIGHT, opcode.INVERT, opcode.AND, opcode.OR, opcode.XOR, opcode
.EQUAL, opcode.NOTEQUAL, opcode.SIGN, opcode.ABS, opcode.NEGATE,
opcode.INC, opcode.DEC, opcode.ADD, opcode.SUB, opcode.MUL, opcode
.DIV, opcode.MOD, opcode.POW, opcode.SQRT, opcode.MODMUL, opcode
.MODPOW, opcode.SHL, opcode.SHR, opcode.NOT, opcode.BOOLAND, opcode
.BOOLOR, opcode.NZ, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, opcode.LT,
opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX, opcode
.WITHIN, opcode.PACKMAP, opcode.PACKSTRUCT, opcode.PACK, opcode
.UNPACK, opcode.NEWARRAY0, opcode.NEWARRAY, opcode.NEWARRAYT, opcode
.NEWSTRUCT0, opcode.NEWSTRUCT, opcode.NEWMAP, opcode.SIZE, opcode
.HASKEY, opcode.KEYS, opcode.VALUES, opcode.PICKITEM, opcode.APPEND,
opcode.SETITEM, opcode.REVERSEITEMS, opcode.REMOVE, opcode.CLEARITEMS,
opcode.POPITEM, opcode.ISNULL, opcode.ISTYPE, opcode.CONVERT, opcode
.ABORTMSG, opcode.ASSERTMSG
pkg/network/server.go:1395:3 exhaustive missing
cases in switch of type network.CommandType: network.CMDNotFound,
network.CMDReject, network.CMDFilterLoad, network.CMDFilterAdd, network
.CMDFilterClear, network.CMDMerkleBlock, network.CMDAlert
pkg/network/server_test.go:532:3 exhaustive missing
cases in switch of type network.CommandType: network.CMDVersion, network
.CMDVerack, network.CMDGetAddr, network.CMDAddr, network.CMDPing,
network.CMDPong, network.CMDGetHeaders, network.CMDHeaders, network
.CMDGetBlocks, network.CMDMempool, network.CMDInv, network.CMDGetData,
network.CMDGetBlockByIndex, network.CMDGetMPTData, network.CMDMPTData,
network.CMDReject, network.CMDFilterLoad, network.CMDFilterAdd, network
.CMDFilterClear, network.CMDMerkleBlock, network.CMDAlert
pkg/network/server_test.go:817:4 exhaustive missing
cases in switch of type network.CommandType: network.CMDVersion, network
.CMDVerack, network.CMDGetAddr, network.CMDAddr, network.CMDPing,
network.CMDPong, network.CMDGetHeaders, network.CMDHeaders, network
.CMDGetBlocks, network.CMDMempool, network.CMDInv, network.CMDGetData,
network.CMDGetBlockByIndex, network.CMDNotFound, network.CMDTX, network
.CMDBlock, network.CMDExtensible, network.CMDP2PNotaryRequest, network
.CMDGetMPTData, network.CMDReject, network.CMDFilterLoad, network
.CMDFilterAdd, network.CMDFilterClear, network.CMDMerkleBlock, network
.CMDAlert
pkg/core/native/designate.go:262:2 exhaustive missing
cases in switch of type noderoles.Role: noderoles.NeoFSAlphabet
pkg/neorpc/rpcevent/filter.go:36:2 exhaustive missing cases in switch
of type neorpc.EventID: neorpc.InvalidEventID, neorpc.MissedEventID
pkg/consensus/recovery_message.go:145:2 exhaustive missing
cases in switch of type dbft.MessageType: dbft.PreCommitType, dbft
.RecoveryRequestType, dbft.RecoveryMessageType
cli/cmdargs/parser.go:202:3 exhaustive missing cases in switch of type
transaction.WitnessScope: transaction.None, transaction.CalledByEntry,
transaction.Rules, transaction.Global
```
Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-09-26 11:30:54 +03:00
|
|
|
default:
|
2021-04-22 17:22:09 +03:00
|
|
|
}
|
|
|
|
|
2022-02-26 17:02:10 +03:00
|
|
|
if !ok || maxObjects < len(objs) {
|
2021-04-22 17:22:09 +03:00
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if objs == nil {
|
2023-04-03 13:34:24 +03:00
|
|
|
objs = []any{}
|
2021-04-22 17:22:09 +03:00
|
|
|
}
|
|
|
|
return objs, true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *pathParser) nextToken() (pathTokenType, string) {
|
|
|
|
var (
|
|
|
|
typ pathTokenType
|
|
|
|
value string
|
|
|
|
ok = true
|
|
|
|
numRead = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
if p.i >= len(p.s) {
|
|
|
|
return pathInvalid, ""
|
|
|
|
}
|
|
|
|
|
|
|
|
switch c := p.s[p.i]; c {
|
|
|
|
case '$':
|
|
|
|
typ = pathRoot
|
|
|
|
case '.':
|
|
|
|
typ = pathDot
|
|
|
|
case '[':
|
|
|
|
typ = pathLeftBracket
|
|
|
|
case ']':
|
|
|
|
typ = pathRightBracket
|
|
|
|
case '*':
|
|
|
|
typ = pathAsterisk
|
|
|
|
case ',':
|
|
|
|
typ = pathComma
|
|
|
|
case ':':
|
|
|
|
typ = pathColon
|
|
|
|
case '\'':
|
|
|
|
typ = pathString
|
|
|
|
value, numRead, ok = p.parseString()
|
|
|
|
default:
|
|
|
|
switch {
|
|
|
|
case c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'):
|
|
|
|
typ = pathIdentifier
|
|
|
|
value, numRead, ok = p.parseIdent()
|
|
|
|
case c == '-' || ('0' <= c && c <= '9'):
|
|
|
|
typ = pathNumber
|
|
|
|
value, numRead, ok = p.parseNumber()
|
|
|
|
default:
|
|
|
|
return pathInvalid, ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
return pathInvalid, ""
|
|
|
|
}
|
|
|
|
|
|
|
|
p.i += numRead
|
|
|
|
return typ, value
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:30:09 +03:00
|
|
|
// parseString parses a JSON string surrounded by single quotes.
|
|
|
|
// It returns the number of characters consumed and true on success.
|
2021-04-22 17:22:09 +03:00
|
|
|
func (p *pathParser) parseString() (string, int, bool) {
|
|
|
|
var end int
|
|
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
|
|
if p.s[end] == '\'' {
|
|
|
|
return p.s[p.i : end+1], end + 1 - p.i, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", 0, false
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:30:09 +03:00
|
|
|
// parseIdent parses an alphanumeric identifier.
|
|
|
|
// It returns the number of characters consumed and true on success.
|
2021-04-22 17:22:09 +03:00
|
|
|
func (p *pathParser) parseIdent() (string, int, bool) {
|
|
|
|
var end int
|
|
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
|
|
c := p.s[end]
|
|
|
|
if c != '_' && !('a' <= c && c <= 'z') &&
|
|
|
|
!('A' <= c && c <= 'Z') && !('0' <= c && c <= '9') {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.s[p.i:end], end - p.i, true
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:30:09 +03:00
|
|
|
// parseNumber parses an integer number.
|
2021-04-22 17:22:09 +03:00
|
|
|
// Only string representation is returned, size-checking is done on the first use.
|
2022-04-20 21:30:09 +03:00
|
|
|
// It also returns the number of characters consumed and true on success.
|
2021-04-22 17:22:09 +03:00
|
|
|
func (p *pathParser) parseNumber() (string, int, bool) {
|
|
|
|
var end int
|
|
|
|
for end = p.i + 1; end < len(p.s); end++ {
|
|
|
|
c := p.s[end]
|
|
|
|
if c < '0' || '9' < c {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.s[p.i:end], end - p.i, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// processDot handles `.` operator.
|
|
|
|
// It either descends 1 level down or performs recursive descent.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) processDot(objs []any) ([]any, bool) {
|
2021-04-22 17:22:09 +03:00
|
|
|
typ, value := p.nextToken()
|
|
|
|
switch typ {
|
|
|
|
case pathAsterisk:
|
|
|
|
return p.descend(objs)
|
|
|
|
case pathDot:
|
|
|
|
return p.descendRecursive(objs)
|
|
|
|
case pathIdentifier:
|
|
|
|
return p.descendByIdent(objs, value)
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// descend descends 1 level down.
|
|
|
|
// It flattens arrays and returns map values for maps.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descend(objs []any) ([]any, bool) {
|
2021-04-30 10:35:33 +03:00
|
|
|
if p.depth <= 0 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
p.depth--
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
var values []any
|
2021-04-22 17:22:09 +03:00
|
|
|
for i := range objs {
|
|
|
|
switch obj := objs[i].(type) {
|
2023-04-03 13:34:24 +03:00
|
|
|
case []any:
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+len(obj) {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
values = append(values, obj...)
|
2021-05-07 19:48:57 +03:00
|
|
|
case json.OrderedObject:
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+len(obj) {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-05-07 19:48:57 +03:00
|
|
|
for i := range obj {
|
|
|
|
values = append(values, obj[i].Value)
|
2021-04-22 17:22:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// descendRecursive performs recursive descent.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descendRecursive(objs []any) ([]any, bool) {
|
2021-04-22 17:22:09 +03:00
|
|
|
typ, val := p.nextToken()
|
|
|
|
if typ != pathIdentifier {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
var values []any
|
2021-04-22 17:22:09 +03:00
|
|
|
|
|
|
|
for len(objs) > 0 {
|
2021-04-30 10:35:33 +03:00
|
|
|
newObjs, _ := p.descendByIdentAux(objs, false, val)
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+len(newObjs) {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
values = append(values, newObjs...)
|
|
|
|
objs, _ = p.descend(objs)
|
|
|
|
}
|
|
|
|
|
|
|
|
return values, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// descendByIdent performs map's field access by name.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descendByIdent(objs []any, names ...string) ([]any, bool) {
|
2021-04-30 10:35:33 +03:00
|
|
|
return p.descendByIdentAux(objs, true, names...)
|
|
|
|
}
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descendByIdentAux(objs []any, checkDepth bool, names ...string) ([]any, bool) {
|
2021-04-30 10:35:33 +03:00
|
|
|
if checkDepth {
|
|
|
|
if p.depth <= 0 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
p.depth--
|
|
|
|
}
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
var values []any
|
2021-04-22 17:22:09 +03:00
|
|
|
for i := range objs {
|
2021-05-07 19:48:57 +03:00
|
|
|
obj, ok := objs[i].(json.OrderedObject)
|
2021-04-22 17:22:09 +03:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for j := range names {
|
2021-05-07 19:48:57 +03:00
|
|
|
for k := range obj {
|
|
|
|
if obj[k].Key == names[j] {
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+1 {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-05-07 19:48:57 +03:00
|
|
|
values = append(values, obj[k].Value)
|
|
|
|
break
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return values, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// descendByIndex performs array access by index.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descendByIndex(objs []any, indices ...int) ([]any, bool) {
|
2021-04-30 10:35:33 +03:00
|
|
|
if p.depth <= 0 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
p.depth--
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
var values []any
|
2021-04-22 17:22:09 +03:00
|
|
|
for i := range objs {
|
2023-04-03 13:34:24 +03:00
|
|
|
obj, ok := objs[i].([]any)
|
2021-04-22 17:22:09 +03:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, j := range indices {
|
|
|
|
if j < 0 {
|
|
|
|
j += len(obj)
|
|
|
|
}
|
|
|
|
if 0 <= j && j < len(obj) {
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+1 {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
values = append(values, obj[j])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// processLeftBracket processes index expressions which can be either
|
|
|
|
// array/map access, array sub-slice or union of indices.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) processLeftBracket(objs []any) ([]any, bool) {
|
2021-04-22 17:22:09 +03:00
|
|
|
typ, value := p.nextToken()
|
|
|
|
switch typ {
|
|
|
|
case pathAsterisk:
|
|
|
|
typ, _ := p.nextToken()
|
|
|
|
if typ != pathRightBracket {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.descend(objs)
|
|
|
|
case pathColon:
|
|
|
|
return p.processSlice(objs, 0)
|
|
|
|
case pathNumber:
|
|
|
|
subTyp, _ := p.nextToken()
|
|
|
|
switch subTyp {
|
|
|
|
case pathColon:
|
|
|
|
index, err := strconv.ParseInt(value, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.processSlice(objs, int(index))
|
|
|
|
case pathComma:
|
|
|
|
return p.processUnion(objs, pathNumber, value)
|
|
|
|
case pathRightBracket:
|
|
|
|
index, err := strconv.ParseInt(value, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.descendByIndex(objs, int(index))
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
case pathString:
|
|
|
|
subTyp, _ := p.nextToken()
|
|
|
|
switch subTyp {
|
|
|
|
case pathComma:
|
|
|
|
return p.processUnion(objs, pathString, value)
|
|
|
|
case pathRightBracket:
|
|
|
|
s := strings.Trim(value, "'")
|
|
|
|
err := json.Unmarshal([]byte(`"`+s+`"`), &s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
return p.descendByIdent(objs, s)
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// processUnion processes union of multiple indices.
|
|
|
|
// firstTyp is assumed to be either pathNumber or pathString.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) processUnion(objs []any, firstTyp pathTokenType, firstVal string) ([]any, bool) {
|
2021-04-22 17:22:09 +03:00
|
|
|
items := []string{firstVal}
|
|
|
|
for {
|
|
|
|
typ, val := p.nextToken()
|
|
|
|
if typ != firstTyp {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
items = append(items, val)
|
2021-05-13 17:26:38 +03:00
|
|
|
typ, _ = p.nextToken()
|
2021-04-22 17:22:09 +03:00
|
|
|
if typ == pathRightBracket {
|
|
|
|
break
|
|
|
|
} else if typ != pathComma {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch firstTyp {
|
|
|
|
case pathNumber:
|
|
|
|
values := make([]int, len(items))
|
|
|
|
for i := range items {
|
|
|
|
index, err := strconv.ParseInt(items[i], 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
values[i] = int(index)
|
|
|
|
}
|
|
|
|
return p.descendByIndex(objs, values...)
|
|
|
|
case pathString:
|
|
|
|
for i := range items {
|
|
|
|
s := strings.Trim(items[i], "'")
|
|
|
|
err := json.Unmarshal([]byte(`"`+s+`"`), &items[i])
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p.descendByIdent(objs, items...)
|
|
|
|
default:
|
|
|
|
panic("token in union must be either number or string")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:30:09 +03:00
|
|
|
// processSlice processes a slice with the specified start index.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) processSlice(objs []any, start int) ([]any, bool) {
|
2021-04-22 17:22:09 +03:00
|
|
|
typ, val := p.nextToken()
|
|
|
|
switch typ {
|
|
|
|
case pathNumber:
|
|
|
|
typ, _ := p.nextToken()
|
|
|
|
if typ != pathRightBracket {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
index, err := strconv.ParseInt(val, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.descendByRange(objs, start, int(index))
|
|
|
|
case pathRightBracket:
|
|
|
|
return p.descendByRange(objs, start, 0)
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// descendByRange is similar to descend but skips maps and returns sub-slices for arrays.
|
2023-04-03 13:34:24 +03:00
|
|
|
func (p *pathParser) descendByRange(objs []any, start, end int) ([]any, bool) {
|
2021-04-30 10:35:33 +03:00
|
|
|
if p.depth <= 0 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
p.depth--
|
|
|
|
|
2023-04-03 13:34:24 +03:00
|
|
|
var values []any
|
2021-04-22 17:22:09 +03:00
|
|
|
for i := range objs {
|
2023-04-03 13:34:24 +03:00
|
|
|
arr, ok := objs[i].([]any)
|
2021-04-22 17:22:09 +03:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
subStart := start
|
|
|
|
if subStart < 0 {
|
|
|
|
subStart += len(arr)
|
|
|
|
}
|
|
|
|
|
|
|
|
subEnd := end
|
|
|
|
if subEnd <= 0 {
|
|
|
|
subEnd += len(arr)
|
|
|
|
}
|
|
|
|
|
2024-08-23 22:09:20 +03:00
|
|
|
subEnd = min(subEnd, len(arr))
|
2021-04-22 17:22:09 +03:00
|
|
|
|
|
|
|
if subEnd <= subStart {
|
|
|
|
continue
|
|
|
|
}
|
2022-02-26 17:02:10 +03:00
|
|
|
if maxObjects < len(values)+subEnd-subStart {
|
|
|
|
return nil, false
|
|
|
|
}
|
2021-04-22 17:22:09 +03:00
|
|
|
values = append(values, arr[subStart:subEnd]...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return values, true
|
|
|
|
}
|