Files
sift/vendor/github.com/itchyny/gojq/operator.go
T
kyle 9444a35322 p1: /v2/scrape, /v1/fetch, auth, CLI, contract tests
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.
2026-09-22 21:54:01 -07:00

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
}