加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
spec_range.go 3.11 KB
一键复制 编辑 原始数据 按行查看 历史
andeyalee 提交于 2021-08-05 21:34 . feat: support 'range' tpl function #12
package tagexpr
import (
"context"
"reflect"
"regexp"
)
type rangeCtxKey string
const (
rangeKey rangeCtxKey = "#k"
rangeValue rangeCtxKey = "#v"
rangeLen rangeCtxKey = "##"
)
type rangeKvExprNode struct {
exprBackground
ctxKey rangeCtxKey
boolOpposite *bool
signOpposite *bool
}
func (p *Expr) readRangeKvExprNode(expr *string) ExprNode {
name, boolOpposite, signOpposite, found := findRangeKv(expr)
if !found {
return nil
}
operand := &rangeKvExprNode{
ctxKey: rangeCtxKey(name),
boolOpposite: boolOpposite,
signOpposite: signOpposite,
}
// fmt.Printf("operand: %#v\n", operand)
return operand
}
var rangeKvRegexp = regexp.MustCompile(`^([\!\+\-]*)(#[kv#])([\)\[\],\+\-\*\/%><\|&!=\^ \t\\]|$)`)
func findRangeKv(expr *string) (name string, boolOpposite, signOpposite *bool, found bool) {
raw := *expr
a := rangeKvRegexp.FindAllStringSubmatch(raw, -1)
if len(a) != 1 {
return
}
r := a[0]
name = r[2]
*expr = (*expr)[len(a[0][0])-len(r[3]):]
prefix := r[1]
if len(prefix) == 0 {
found = true
return
}
_, boolOpposite, signOpposite = getBoolAndSignOpposite(&prefix)
found = true
return
}
func (re *rangeKvExprNode) Run(ctx context.Context, _ string, _ *TagExpr) interface{} {
var v interface{}
switch val := ctx.Value(re.ctxKey).(type) {
case reflect.Value:
if !val.IsValid() || !val.CanInterface() {
return nil
}
v = val.Interface()
default:
v = val
}
return realValue(v, re.boolOpposite, re.signOpposite)
}
type rangeFuncExprNode struct {
exprBackground
object ExprNode
elemExprNode ExprNode
boolOpposite *bool
signOpposite *bool
}
// range($, gt($v,10))
// range($, $v>10)
func readRangeFuncExprNode(p *Expr, expr *string) ExprNode {
boolOpposite, signOpposite, args, found := p.parseFuncSign("range", expr)
if !found {
return nil
}
if len(args) != 2 {
return nil
}
return &rangeFuncExprNode{
boolOpposite: boolOpposite,
signOpposite: signOpposite,
object: args[0],
elemExprNode: args[1],
}
}
func (e *rangeFuncExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} {
var r []interface{}
obj := e.object.Run(ctx, currField, tagExpr)
// fmt.Printf("%v\n", obj)
objval := reflect.ValueOf(obj)
switch objval.Kind() {
case reflect.Array, reflect.Slice:
count := objval.Len()
r = make([]interface{}, count)
ctx = context.WithValue(ctx, rangeLen, count)
for i := 0; i < count; i++ {
// fmt.Printf("%#v, (%v)\n", e.elemExprNode, objval.Index(i))
r[i] = realValue(e.elemExprNode.Run(
context.WithValue(
context.WithValue(
ctx,
rangeKey, i,
),
rangeValue, objval.Index(i),
),
currField, tagExpr,
), e.boolOpposite, e.signOpposite)
}
case reflect.Map:
keys := objval.MapKeys()
count := len(keys)
r = make([]interface{}, count)
ctx = context.WithValue(ctx, rangeLen, count)
for i, key := range keys {
r[i] = realValue(e.elemExprNode.Run(
context.WithValue(
context.WithValue(
ctx,
rangeKey, key,
),
rangeValue, objval.MapIndex(key),
),
currField, tagExpr,
), e.boolOpposite, e.signOpposite)
}
default:
}
return r
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化