Single Fetcher.Fetch on the Guard that holds DenyPrefixes. skipTlsVerification is ignored. No 502. keys add writes the secret only to --out. Release binary has no -test-allow-prefix.
558 lines
10 KiB
Go
558 lines
10 KiB
Go
package gojq
|
|
|
|
import (
|
|
"encoding/json"
|
|
"maps"
|
|
"math"
|
|
"math/big"
|
|
"strings"
|
|
)
|
|
|
|
// Operator ...
|
|
type Operator int
|
|
|
|
// Operators ...
|
|
const (
|
|
OpPipe Operator = iota + 1
|
|
OpComma
|
|
OpAdd
|
|
OpSub
|
|
OpMul
|
|
OpDiv
|
|
OpMod
|
|
OpEq
|
|
OpNe
|
|
OpGt
|
|
OpLt
|
|
OpGe
|
|
OpLe
|
|
OpAnd
|
|
OpOr
|
|
OpAlt
|
|
OpAssign
|
|
OpModify
|
|
OpUpdateAdd
|
|
OpUpdateSub
|
|
OpUpdateMul
|
|
OpUpdateDiv
|
|
OpUpdateMod
|
|
OpUpdateAlt
|
|
)
|
|
|
|
// String implements [fmt.Stringer].
|
|
func (op Operator) String() string {
|
|
switch op {
|
|
case OpPipe:
|
|
return "|"
|
|
case OpComma:
|
|
return ","
|
|
case OpAdd:
|
|
return "+"
|
|
case OpSub:
|
|
return "-"
|
|
case OpMul:
|
|
return "*"
|
|
case OpDiv:
|
|
return "/"
|
|
case OpMod:
|
|
return "%"
|
|
case OpEq:
|
|
return "=="
|
|
case OpNe:
|
|
return "!="
|
|
case OpGt:
|
|
return ">"
|
|
case OpLt:
|
|
return "<"
|
|
case OpGe:
|
|
return ">="
|
|
case OpLe:
|
|
return "<="
|
|
case OpAnd:
|
|
return "and"
|
|
case OpOr:
|
|
return "or"
|
|
case OpAlt:
|
|
return "//"
|
|
case OpAssign:
|
|
return "="
|
|
case OpModify:
|
|
return "|="
|
|
case OpUpdateAdd:
|
|
return "+="
|
|
case OpUpdateSub:
|
|
return "-="
|
|
case OpUpdateMul:
|
|
return "*="
|
|
case OpUpdateDiv:
|
|
return "/="
|
|
case OpUpdateMod:
|
|
return "%="
|
|
case OpUpdateAlt:
|
|
return "//="
|
|
default:
|
|
panic(op)
|
|
}
|
|
}
|
|
|
|
// GoString implements [fmt.GoStringer].
|
|
func (op Operator) GoString() (str string) {
|
|
defer func() { str = "gojq." + str }()
|
|
switch op {
|
|
case Operator(0):
|
|
return "Operator(0)"
|
|
case OpPipe:
|
|
return "OpPipe"
|
|
case OpComma:
|
|
return "OpComma"
|
|
case OpAdd:
|
|
return "OpAdd"
|
|
case OpSub:
|
|
return "OpSub"
|
|
case OpMul:
|
|
return "OpMul"
|
|
case OpDiv:
|
|
return "OpDiv"
|
|
case OpMod:
|
|
return "OpMod"
|
|
case OpEq:
|
|
return "OpEq"
|
|
case OpNe:
|
|
return "OpNe"
|
|
case OpGt:
|
|
return "OpGt"
|
|
case OpLt:
|
|
return "OpLt"
|
|
case OpGe:
|
|
return "OpGe"
|
|
case OpLe:
|
|
return "OpLe"
|
|
case OpAnd:
|
|
return "OpAnd"
|
|
case OpOr:
|
|
return "OpOr"
|
|
case OpAlt:
|
|
return "OpAlt"
|
|
case OpAssign:
|
|
return "OpAssign"
|
|
case OpModify:
|
|
return "OpModify"
|
|
case OpUpdateAdd:
|
|
return "OpUpdateAdd"
|
|
case OpUpdateSub:
|
|
return "OpUpdateSub"
|
|
case OpUpdateMul:
|
|
return "OpUpdateMul"
|
|
case OpUpdateDiv:
|
|
return "OpUpdateDiv"
|
|
case OpUpdateMod:
|
|
return "OpUpdateMod"
|
|
case OpUpdateAlt:
|
|
return "OpUpdateAlt"
|
|
default:
|
|
panic(op)
|
|
}
|
|
}
|
|
|
|
func (op Operator) getFunc() string {
|
|
switch op {
|
|
case OpAdd, OpUpdateAdd:
|
|
return "_add"
|
|
case OpSub, OpUpdateSub:
|
|
return "_subtract"
|
|
case OpMul, OpUpdateMul:
|
|
return "_multiply"
|
|
case OpDiv, OpUpdateDiv:
|
|
return "_divide"
|
|
case OpMod, OpUpdateMod:
|
|
return "_modulo"
|
|
case OpEq:
|
|
return "_equal"
|
|
case OpNe:
|
|
return "_notequal"
|
|
case OpGt:
|
|
return "_greater"
|
|
case OpLt:
|
|
return "_less"
|
|
case OpGe:
|
|
return "_greatereq"
|
|
case OpLe:
|
|
return "_lesseq"
|
|
case OpAssign:
|
|
return "_assign"
|
|
case OpModify:
|
|
return "_modify"
|
|
case OpUpdateAlt:
|
|
return "_alternative"
|
|
default:
|
|
panic(op)
|
|
}
|
|
}
|
|
|
|
func binopTypeSwitch[T any](
|
|
l, r any,
|
|
callbackInts func(_, _ int) T,
|
|
callbackFloats func(_, _ float64) T,
|
|
callbackBigInts func(_, _ *big.Int) T,
|
|
callbackStrings func(_, _ string) T,
|
|
callbackArrays func(_, _ []any) T,
|
|
callbackMaps func(_, _ map[string]any) T,
|
|
fallback func(_, _ any) T) T {
|
|
if n, ok := l.(json.Number); ok {
|
|
l = parseNumber(n)
|
|
}
|
|
if n, ok := r.(json.Number); ok {
|
|
r = parseNumber(n)
|
|
}
|
|
switch l := l.(type) {
|
|
case int:
|
|
switch r := r.(type) {
|
|
case int:
|
|
return callbackInts(l, r)
|
|
case float64:
|
|
return callbackFloats(float64(l), r)
|
|
case *big.Int:
|
|
return callbackBigInts(big.NewInt(int64(l)), r)
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
case float64:
|
|
switch r := r.(type) {
|
|
case int:
|
|
return callbackFloats(l, float64(r))
|
|
case float64:
|
|
return callbackFloats(l, r)
|
|
case *big.Int:
|
|
return callbackFloats(l, bigToFloat(r))
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
case *big.Int:
|
|
switch r := r.(type) {
|
|
case int:
|
|
return callbackBigInts(l, big.NewInt(int64(r)))
|
|
case float64:
|
|
return callbackFloats(bigToFloat(l), r)
|
|
case *big.Int:
|
|
return callbackBigInts(l, r)
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
case string:
|
|
switch r := r.(type) {
|
|
case string:
|
|
return callbackStrings(l, r)
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
case []any:
|
|
switch r := r.(type) {
|
|
case []any:
|
|
return callbackArrays(l, r)
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
case map[string]any:
|
|
switch r := r.(type) {
|
|
case map[string]any:
|
|
return callbackMaps(l, r)
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
default:
|
|
return fallback(l, r)
|
|
}
|
|
}
|
|
|
|
func funcOpPlus(v any) any {
|
|
switch v := v.(type) {
|
|
case int:
|
|
return v
|
|
case float64:
|
|
return v
|
|
case *big.Int:
|
|
return v
|
|
case json.Number:
|
|
return v
|
|
default:
|
|
return &unaryTypeError{"plus", v}
|
|
}
|
|
}
|
|
|
|
func negate(v int) any {
|
|
if v == math.MinInt {
|
|
return new(big.Int).Neg(big.NewInt(int64(v)))
|
|
}
|
|
return -v
|
|
}
|
|
|
|
func funcOpNegate(v any) any {
|
|
switch v := v.(type) {
|
|
case int:
|
|
return negate(v)
|
|
case float64:
|
|
return -v
|
|
case *big.Int:
|
|
return new(big.Int).Neg(v)
|
|
case json.Number:
|
|
if strings.HasPrefix(v.String(), "-") {
|
|
return v[1:]
|
|
}
|
|
return "-" + v
|
|
default:
|
|
return &unaryTypeError{"negate", v}
|
|
}
|
|
}
|
|
|
|
func funcOpAdd(_, l, r any) any {
|
|
return binopTypeSwitch(l, r,
|
|
func(l, r int) any {
|
|
if v := l + r; (v >= l) == (r >= 0) {
|
|
return v
|
|
}
|
|
x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
|
|
return x.Add(x, y)
|
|
},
|
|
func(l, r float64) any { return l + r },
|
|
func(l, r *big.Int) any { return new(big.Int).Add(l, r) },
|
|
func(l, r string) any { return l + r },
|
|
func(l, r []any) any {
|
|
if len(l) == 0 {
|
|
return r
|
|
}
|
|
if len(r) == 0 {
|
|
return l
|
|
}
|
|
v := make([]any, len(l)+len(r))
|
|
copy(v, l)
|
|
copy(v[len(l):], r)
|
|
return v
|
|
},
|
|
func(l, r map[string]any) any {
|
|
if len(l) == 0 {
|
|
return r
|
|
}
|
|
if len(r) == 0 {
|
|
return l
|
|
}
|
|
m := make(map[string]any, len(l)+len(r))
|
|
maps.Copy(m, l)
|
|
maps.Copy(m, r)
|
|
return m
|
|
},
|
|
func(l, r any) any {
|
|
if l == nil {
|
|
return r
|
|
}
|
|
if r == nil {
|
|
return l
|
|
}
|
|
return &binopTypeError{"add", l, r}
|
|
},
|
|
)
|
|
}
|
|
|
|
func funcOpSub(_, l, r any) any {
|
|
return binopTypeSwitch(l, r,
|
|
func(l, r int) any {
|
|
if v := l - r; (v <= l) == (r >= 0) {
|
|
return v
|
|
}
|
|
x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
|
|
return x.Sub(x, y)
|
|
},
|
|
func(l, r float64) any { return l - r },
|
|
func(l, r *big.Int) any { return new(big.Int).Sub(l, r) },
|
|
func(l, r string) any { return &binopTypeError{"subtract", l, r} },
|
|
func(l, r []any) any {
|
|
v := make([]any, 0, len(l))
|
|
L:
|
|
for _, l := range l {
|
|
for _, r := range r {
|
|
if Compare(l, r) == 0 {
|
|
continue L
|
|
}
|
|
}
|
|
v = append(v, l)
|
|
}
|
|
return v
|
|
},
|
|
func(l, r map[string]any) any { return &binopTypeError{"subtract", l, r} },
|
|
func(l, r any) any { return &binopTypeError{"subtract", l, r} },
|
|
)
|
|
}
|
|
|
|
func funcOpMul(_, l, r any) any {
|
|
return binopTypeSwitch(l, r,
|
|
func(l, r int) any {
|
|
if r == -1 {
|
|
return negate(l)
|
|
}
|
|
if v := l * r; r == 0 || v/r == l {
|
|
return v
|
|
}
|
|
x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
|
|
return x.Mul(x, y)
|
|
},
|
|
func(l, r float64) any { return l * r },
|
|
func(l, r *big.Int) any { return new(big.Int).Mul(l, r) },
|
|
func(l, r string) any { return &binopTypeError{"multiply", l, r} },
|
|
func(l, r []any) any { return &binopTypeError{"multiply", l, r} },
|
|
deepMergeObjects,
|
|
func(l, r any) any {
|
|
if l, ok := l.(string); ok {
|
|
if r, ok := toFloat(r); ok {
|
|
return repeatString(l, r)
|
|
}
|
|
}
|
|
if r, ok := r.(string); ok {
|
|
if l, ok := toFloat(l); ok {
|
|
return repeatString(r, l)
|
|
}
|
|
}
|
|
return &binopTypeError{"multiply", l, r}
|
|
},
|
|
)
|
|
}
|
|
|
|
func deepMergeObjects(l, r map[string]any) any {
|
|
m := make(map[string]any, len(l)+len(r))
|
|
maps.Copy(m, l)
|
|
for k, v := range r {
|
|
if mk, ok := m[k]; ok {
|
|
if mk, ok := mk.(map[string]any); ok {
|
|
if w, ok := v.(map[string]any); ok {
|
|
v = deepMergeObjects(mk, w)
|
|
}
|
|
}
|
|
}
|
|
m[k] = v
|
|
}
|
|
return m
|
|
}
|
|
|
|
func repeatString(s string, n float64) any {
|
|
if lt(n, 0) {
|
|
return nil
|
|
}
|
|
c := int(min(n, math.MaxInt32))
|
|
if uint64(len(s))*uint64(c) >= math.MaxInt32 {
|
|
return &repeatStringTooLargeError{s, n}
|
|
}
|
|
return strings.Repeat(s, c)
|
|
}
|
|
|
|
func funcOpDiv(_, l, r any) any {
|
|
return binopTypeSwitch(l, r,
|
|
func(l, r int) any {
|
|
switch r {
|
|
case 0:
|
|
return &zeroDivisionError{l, r}
|
|
case -1:
|
|
return negate(l)
|
|
default:
|
|
if l%r == 0 {
|
|
return l / r
|
|
}
|
|
return float64(l) / float64(r)
|
|
}
|
|
},
|
|
func(l, r float64) any {
|
|
if r == 0.0 {
|
|
return &zeroDivisionError{l, r}
|
|
}
|
|
return l / r
|
|
},
|
|
func(l, r *big.Int) any {
|
|
if r.Sign() == 0 {
|
|
return &zeroDivisionError{l, r}
|
|
}
|
|
d, m := new(big.Int).DivMod(l, r, new(big.Int))
|
|
if m.Sign() == 0 {
|
|
return d
|
|
}
|
|
return bigToFloat(l) / bigToFloat(r)
|
|
},
|
|
func(l, r string) any {
|
|
if l == "" {
|
|
return []any{}
|
|
}
|
|
xs := strings.Split(l, r)
|
|
vs := make([]any, len(xs))
|
|
for i, x := range xs {
|
|
vs[i] = x
|
|
}
|
|
return vs
|
|
},
|
|
func(l, r []any) any { return &binopTypeError{"divide", l, r} },
|
|
func(l, r map[string]any) any { return &binopTypeError{"divide", l, r} },
|
|
func(l, r any) any { return &binopTypeError{"divide", l, r} },
|
|
)
|
|
}
|
|
|
|
func funcOpMod(_, l, r any) any {
|
|
return binopTypeSwitch(l, r,
|
|
func(l, r int) any {
|
|
switch r {
|
|
case 0:
|
|
return &zeroModuloError{l, r}
|
|
case -1:
|
|
return 0
|
|
default:
|
|
return l % r
|
|
}
|
|
},
|
|
func(l, r float64) any {
|
|
if math.IsNaN(l) || math.IsNaN(r) {
|
|
return math.NaN()
|
|
}
|
|
ri := floatToInt(r)
|
|
if ri == 0 {
|
|
return &zeroModuloError{l, r}
|
|
}
|
|
return floatToInt(l) % ri
|
|
},
|
|
func(l, r *big.Int) any {
|
|
if r.Sign() == 0 {
|
|
return &zeroModuloError{l, r}
|
|
}
|
|
return new(big.Int).Rem(l, r)
|
|
},
|
|
func(l, r string) any { return &binopTypeError{"modulo", l, r} },
|
|
func(l, r []any) any { return &binopTypeError{"modulo", l, r} },
|
|
func(l, r map[string]any) any { return &binopTypeError{"modulo", l, r} },
|
|
func(l, r any) any { return &binopTypeError{"modulo", l, r} },
|
|
)
|
|
}
|
|
|
|
func funcOpAlt(_, l, r any) any {
|
|
if l == nil || l == false {
|
|
return r
|
|
}
|
|
return l
|
|
}
|
|
|
|
func funcOpEq(_, l, r any) any {
|
|
return Compare(l, r) == 0
|
|
}
|
|
|
|
func funcOpNe(_, l, r any) any {
|
|
return Compare(l, r) != 0
|
|
}
|
|
|
|
func funcOpGt(_, l, r any) any {
|
|
return Compare(l, r) > 0
|
|
}
|
|
|
|
func funcOpLt(_, l, r any) any {
|
|
return Compare(l, r) < 0
|
|
}
|
|
|
|
func funcOpGe(_, l, r any) any {
|
|
return Compare(l, r) >= 0
|
|
}
|
|
|
|
func funcOpLe(_, l, r any) any {
|
|
return Compare(l, r) <= 0
|
|
}
|