Source File
functions.go
Belonging Package
github.com/jmespath/go-jmespath
package jmespath
import (
)
type jpFunction func(arguments []interface{}) (interface{}, error)
type jpType string
const (
jpUnknown jpType = "unknown"
jpNumber jpType = "number"
jpString jpType = "string"
jpArray jpType = "array"
jpObject jpType = "object"
jpArrayNumber jpType = "array[number]"
jpArrayString jpType = "array[string]"
jpExpref jpType = "expref"
jpAny jpType = "any"
)
type functionEntry struct {
name string
arguments []argSpec
handler jpFunction
hasExpRef bool
}
type argSpec struct {
types []jpType
variadic bool
}
type byExprString struct {
intr *treeInterpreter
node ASTNode
items []interface{}
hasError bool
}
func ( *byExprString) () int {
return len(.items)
}
func ( *byExprString) (, int) {
.items[], .items[] = .items[], .items[]
}
func ( *byExprString) (, int) bool {
, := .intr.Execute(.node, .items[])
if != nil {
return true
}
, := .(string)
if ! {
.hasError = true
return true
}
return <
}
type byExprFloat struct {
intr *treeInterpreter
node ASTNode
items []interface{}
hasError bool
}
func ( *byExprFloat) () int {
return len(.items)
}
func ( *byExprFloat) (, int) {
.items[], .items[] = .items[], .items[]
}
func ( *byExprFloat) (, int) bool {
, := .intr.Execute(.node, .items[])
if != nil {
return true
}
, := .(float64)
if ! {
.hasError = true
return true
}
return <
}
type functionCaller struct {
functionTable map[string]functionEntry
}
func () *functionCaller {
:= &functionCaller{}
.functionTable = map[string]functionEntry{
"length": {
name: "length",
arguments: []argSpec{
{types: []jpType{jpString, jpArray, jpObject}},
},
handler: jpfLength,
},
"starts_with": {
name: "starts_with",
arguments: []argSpec{
{types: []jpType{jpString}},
{types: []jpType{jpString}},
},
handler: jpfStartsWith,
},
"abs": {
name: "abs",
arguments: []argSpec{
{types: []jpType{jpNumber}},
},
handler: jpfAbs,
},
"avg": {
name: "avg",
arguments: []argSpec{
{types: []jpType{jpArrayNumber}},
},
handler: jpfAvg,
},
"ceil": {
name: "ceil",
arguments: []argSpec{
{types: []jpType{jpNumber}},
},
handler: jpfCeil,
},
"contains": {
name: "contains",
arguments: []argSpec{
{types: []jpType{jpArray, jpString}},
{types: []jpType{jpAny}},
},
handler: jpfContains,
},
"ends_with": {
name: "ends_with",
arguments: []argSpec{
{types: []jpType{jpString}},
{types: []jpType{jpString}},
},
handler: jpfEndsWith,
},
"floor": {
name: "floor",
arguments: []argSpec{
{types: []jpType{jpNumber}},
},
handler: jpfFloor,
},
"map": {
name: "amp",
arguments: []argSpec{
{types: []jpType{jpExpref}},
{types: []jpType{jpArray}},
},
handler: jpfMap,
hasExpRef: true,
},
"max": {
name: "max",
arguments: []argSpec{
{types: []jpType{jpArrayNumber, jpArrayString}},
},
handler: jpfMax,
},
"merge": {
name: "merge",
arguments: []argSpec{
{types: []jpType{jpObject}, variadic: true},
},
handler: jpfMerge,
},
"max_by": {
name: "max_by",
arguments: []argSpec{
{types: []jpType{jpArray}},
{types: []jpType{jpExpref}},
},
handler: jpfMaxBy,
hasExpRef: true,
},
"sum": {
name: "sum",
arguments: []argSpec{
{types: []jpType{jpArrayNumber}},
},
handler: jpfSum,
},
"min": {
name: "min",
arguments: []argSpec{
{types: []jpType{jpArrayNumber, jpArrayString}},
},
handler: jpfMin,
},
"min_by": {
name: "min_by",
arguments: []argSpec{
{types: []jpType{jpArray}},
{types: []jpType{jpExpref}},
},
handler: jpfMinBy,
hasExpRef: true,
},
"type": {
name: "type",
arguments: []argSpec{
{types: []jpType{jpAny}},
},
handler: jpfType,
},
"keys": {
name: "keys",
arguments: []argSpec{
{types: []jpType{jpObject}},
},
handler: jpfKeys,
},
"values": {
name: "values",
arguments: []argSpec{
{types: []jpType{jpObject}},
},
handler: jpfValues,
},
"sort": {
name: "sort",
arguments: []argSpec{
{types: []jpType{jpArrayString, jpArrayNumber}},
},
handler: jpfSort,
},
"sort_by": {
name: "sort_by",
arguments: []argSpec{
{types: []jpType{jpArray}},
{types: []jpType{jpExpref}},
},
handler: jpfSortBy,
hasExpRef: true,
},
"join": {
name: "join",
arguments: []argSpec{
{types: []jpType{jpString}},
{types: []jpType{jpArrayString}},
},
handler: jpfJoin,
},
"reverse": {
name: "reverse",
arguments: []argSpec{
{types: []jpType{jpArray, jpString}},
},
handler: jpfReverse,
},
"to_array": {
name: "to_array",
arguments: []argSpec{
{types: []jpType{jpAny}},
},
handler: jpfToArray,
},
"to_string": {
name: "to_string",
arguments: []argSpec{
{types: []jpType{jpAny}},
},
handler: jpfToString,
},
"to_number": {
name: "to_number",
arguments: []argSpec{
{types: []jpType{jpAny}},
},
handler: jpfToNumber,
},
"not_null": {
name: "not_null",
arguments: []argSpec{
{types: []jpType{jpAny}, variadic: true},
},
handler: jpfNotNull,
},
}
return
}
func ( *functionEntry) ( []interface{}) ([]interface{}, error) {
if len(.arguments) == 0 {
return , nil
}
if !.arguments[len(.arguments)-1].variadic {
if len(.arguments) != len() {
return nil, errors.New("incorrect number of args")
}
for , := range .arguments {
:= []
:= .typeCheck()
if != nil {
return nil,
}
}
return , nil
}
if len() < len(.arguments) {
return nil, errors.New("Invalid arity.")
}
return , nil
}
func ( *argSpec) ( interface{}) error {
for , := range .types {
switch {
case jpNumber:
if , := .(float64); {
return nil
}
case jpString:
if , := .(string); {
return nil
}
case jpArray:
if isSliceType() {
return nil
}
case jpObject:
if , := .(map[string]interface{}); {
return nil
}
case jpArrayNumber:
if , := toArrayNum(); {
return nil
}
case jpArrayString:
if , := toArrayStr(); {
return nil
}
case jpAny:
return nil
case jpExpref:
if , := .(expRef); {
return nil
}
}
}
return fmt.Errorf("Invalid type for: %v, expected: %#v", , .types)
}
func ( *functionCaller) ( string, []interface{}, *treeInterpreter) (interface{}, error) {
, := .functionTable[]
if ! {
return nil, errors.New("unknown function: " + )
}
, := .resolveArgs()
if != nil {
return nil,
}
if .hasExpRef {
var []interface{}
= append(, )
= append(, ...)
}
return .handler()
}
func ( []interface{}) (interface{}, error) {
:= [0].(float64)
return math.Abs(), nil
}
func ( []interface{}) (interface{}, error) {
:= [0]
if , := .(string); {
return float64(utf8.RuneCountInString()), nil
} else if isSliceType() {
:= reflect.ValueOf()
return float64(.Len()), nil
} else if , := .(map[string]interface{}); {
return float64(len()), nil
}
return nil, errors.New("could not compute length()")
}
func ( []interface{}) (interface{}, error) {
:= [0].(string)
:= [1].(string)
return strings.HasPrefix(, ), nil
}
:= [0].([]interface{})
:= float64(len())
:= 0.0
for , := range {
+= .(float64)
}
return / , nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(float64)
return math.Ceil(), nil
}
func ( []interface{}) (interface{}, error) {
:= [0]
:= [1]
if , := .(string); {
if , := .(string); {
return strings.Index(, ) != -1, nil
}
return false, nil
:= .([]interface{})
for , := range {
if == {
return true, nil
}
}
return false, nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(string)
:= [1].(string)
return strings.HasSuffix(, ), nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(float64)
return math.Floor(), nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(*treeInterpreter)
:= [1].(expRef)
:= .ref
:= [2].([]interface{})
:= make([]interface{}, 0, len())
for , := range {
, := .Execute(, )
if != nil {
return nil,
}
= append(, )
}
return , nil
}
func ( []interface{}) (interface{}, error) {
if , := toArrayNum([0]); {
if len() == 0 {
return nil, nil
}
if len() == 1 {
return [0], nil
}
:= [0]
for , := range [1:] {
if > {
=
}
}
return , nil
, := toArrayStr([0])
if len() == 0 {
return nil, nil
}
if len() == 1 {
return [0], nil
}
:= [0]
for , := range [1:] {
if > {
=
}
}
return , nil
}
func ( []interface{}) (interface{}, error) {
:= make(map[string]interface{})
for , := range {
:= .(map[string]interface{})
for , := range {
[] =
}
}
return , nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(*treeInterpreter)
:= [1].([]interface{})
:= [2].(expRef)
:= .ref
if len() == 0 {
return nil, nil
} else if len() == 1 {
return [0], nil
}
, := .Execute(, [0])
if != nil {
return nil,
}
switch t := .(type) {
case float64:
:=
:= [0]
for , := range [1:] {
, := .Execute(, )
if != nil {
return nil,
}
, := .(float64)
if ! {
return nil, errors.New("invalid type, must be number")
}
if > {
=
=
}
}
return , nil
case string:
:=
:= [0]
for , := range [1:] {
, := .Execute(, )
if != nil {
return nil,
}
, := .(string)
if ! {
return nil, errors.New("invalid type, must be string")
}
if > {
=
=
}
}
return , nil
default:
return nil, errors.New("invalid type, must be number of string")
}
}
func ( []interface{}) (interface{}, error) {
, := toArrayNum([0])
:= 0.0
for , := range {
+=
}
return , nil
}
func ( []interface{}) (interface{}, error) {
if , := toArrayNum([0]); {
if len() == 0 {
return nil, nil
}
if len() == 1 {
return [0], nil
}
:= [0]
for , := range [1:] {
if < {
=
}
}
return , nil
}
, := toArrayStr([0])
if len() == 0 {
return nil, nil
}
if len() == 1 {
return [0], nil
}
:= [0]
for , := range [1:] {
if < {
=
}
}
return , nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(*treeInterpreter)
:= [1].([]interface{})
:= [2].(expRef)
:= .ref
if len() == 0 {
return nil, nil
} else if len() == 1 {
return [0], nil
}
, := .Execute(, [0])
if != nil {
return nil,
}
if , := .(float64); {
:=
:= [0]
for , := range [1:] {
, := .Execute(, )
if != nil {
return nil,
}
, := .(float64)
if ! {
return nil, errors.New("invalid type, must be number")
}
if < {
=
=
}
}
return , nil
} else if , := .(string); {
:=
:= [0]
for , := range [1:] {
, := .Execute(, )
if != nil {
return nil,
}
, := .(string)
if ! {
return nil, errors.New("invalid type, must be string")
}
if < {
=
=
}
}
return , nil
} else {
return nil, errors.New("invalid type, must be number of string")
}
}
func ( []interface{}) (interface{}, error) {
:= [0]
if , := .(float64); {
return "number", nil
}
if , := .(string); {
return "string", nil
}
if , := .([]interface{}); {
return "array", nil
}
if , := .(map[string]interface{}); {
return "object", nil
}
if == nil {
return "null", nil
}
if == true || == false {
return "boolean", nil
}
return nil, errors.New("unknown type")
}
func ( []interface{}) (interface{}, error) {
:= [0].(map[string]interface{})
:= make([]interface{}, 0, len())
for := range {
= append(, )
}
return , nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(map[string]interface{})
:= make([]interface{}, 0, len())
for , := range {
= append(, )
}
return , nil
}
func ( []interface{}) (interface{}, error) {
if , := toArrayNum([0]); {
:= sort.Float64Slice()
sort.Stable()
:= make([]interface{}, len())
for , := range {
[] =
}
return , nil
, := toArrayStr([0])
:= sort.StringSlice()
sort.Stable()
:= make([]interface{}, len())
for , := range {
[] =
}
return , nil
}
func ( []interface{}) (interface{}, error) {
:= [0].(*treeInterpreter)
:= [1].([]interface{})
:= [2].(expRef)
:= .ref
if len() == 0 {
return , nil
} else if len() == 1 {
return , nil
}
, := .Execute(, [0])
if != nil {
return nil,
}
if , := .(float64); {
:= &byExprFloat{, , , false}
sort.Stable()
if .hasError {
return nil, errors.New("error in sort_by comparison")
}
return , nil
} else if , := .(string); {
:= &byExprString{, , , false}
sort.Stable()
if .hasError {
return nil, errors.New("error in sort_by comparison")
}
return , nil
} else {
return nil, errors.New("invalid type, must be number of string")
}
}
func ( []interface{}) (interface{}, error) {
:= []string{}
for , := range [1].([]interface{}) {
= append(, .(string))
}
return strings.Join(, ), nil
}
func ( []interface{}) (interface{}, error) {
if , := [0].(string); {
:= []rune()
for , := 0, len()-1; < len()/2; , = +1, -1 {
[], [] = [], []
}
return string(), nil
}
:= [0].([]interface{})
:= len()
:= make([]interface{}, )
for , := range {
[-(+1)] =
}
return , nil
}
func ( []interface{}) (interface{}, error) {
if , := [0].([]interface{}); {
return [0], nil
}
return [:1:1], nil
}
func ( []interface{}) (interface{}, error) {
if , := [0].(string); {
return , nil
}
, := json.Marshal([0])
if != nil {
return nil,
}
return string(), nil
}
func ( []interface{}) (interface{}, error) {
:= [0]
if , := .(float64); {
return , nil
}
if , := .(string); {
, := strconv.ParseFloat(, 64)
if != nil {
return nil, nil
}
return , nil
}
if , := .([]interface{}); {
return nil, nil
}
if , := .(map[string]interface{}); {
return nil, nil
}
if == nil {
return nil, nil
}
if == true || == false {
return nil, nil
}
return nil, errors.New("unknown type")
}
func ( []interface{}) (interface{}, error) {
for , := range {
if != nil {
return , nil
}
}
return nil, nil
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |