func bothNodeOperator(left tree.NodeSet, right tree.NodeSet, f *xpFilt, op string) error { var err error for _, l := range left { for _, r := range right { lStr := l.ResValue() rStr := r.ResValue() if eqOps[op] { err = equalsOperator(tree.String(lStr), tree.String(rStr), f, op) if err == nil && f.ctx.String() == tree.True { return nil } } else { err = numberOperator(tree.String(lStr), tree.String(rStr), f, op) if err == nil && f.ctx.String() == tree.True { return nil } } } } f.ctx = tree.Bool(false) return nil }
func checkLang(srcStr, targStr string) tree.Bool { srcLang := language.Make(srcStr) srcRegion, srcRegionConf := srcLang.Region() targLang := language.Make(targStr) targRegion, targRegionConf := targLang.Region() if srcRegionConf == language.Exact && targRegionConf != language.Exact { return tree.Bool(false) } if srcRegion != targRegion && srcRegionConf == language.Exact && targRegionConf == language.Exact { return tree.Bool(false) } _, _, conf := language.NewMatcher([]language.Tag{srcLang}).Match(targLang) return tree.Bool(conf >= language.High) }
func equalsOperator(left, right tree.Result, f *xpFilt, op string) error { _, lOK := left.(tree.Bool) _, rOK := right.(tree.Bool) if lOK || rOK { lTest, lt := left.(tree.IsBool) rTest, rt := right.(tree.IsBool) if !lt || !rt { return fmt.Errorf("Cannot convert argument to boolean") } if op == "=" { f.ctx = tree.Bool(lTest.Bool() == rTest.Bool()) } else { f.ctx = tree.Bool(lTest.Bool() != rTest.Bool()) } return nil } _, lOK = left.(tree.Num) _, rOK = right.(tree.Num) if lOK || rOK { return numberOperator(left, right, f, op) } lStr := left.String() rStr := right.String() if op == "=" { f.ctx = tree.Bool(lStr == rStr) } else { f.ctx = tree.Bool(lStr != rStr) } return nil }
func numberOperator(left, right tree.Result, f *xpFilt, op string) error { lt, lOK := left.(tree.IsNum) rt, rOK := right.(tree.IsNum) if !lOK || !rOK { return fmt.Errorf("Cannot convert data type to number") } ln, rn := lt.Num(), rt.Num() switch op { case "*": f.ctx = ln * rn case "div": if rn != 0 { f.ctx = ln / rn } else { if ln == 0 { f.ctx = tree.Num(math.NaN()) } else { if math.Signbit(float64(ln)) == math.Signbit(float64(rn)) { f.ctx = tree.Num(math.Inf(1)) } else { f.ctx = tree.Num(math.Inf(-1)) } } } case "mod": f.ctx = tree.Num(int(ln) % int(rn)) case "+": f.ctx = ln + rn case "-": f.ctx = ln - rn case "=": f.ctx = tree.Bool(ln == rn) case "!=": f.ctx = tree.Bool(ln != rn) case "<": f.ctx = tree.Bool(ln < rn) case "<=": f.ctx = tree.Bool(ln <= rn) case ">": f.ctx = tree.Bool(ln > rn) case ">=": f.ctx = tree.Bool(ln >= rn) } return nil }
func lang(c tree.Ctx, args ...tree.Result) (tree.Result, error) { lStr := args[0].String() var n tree.Elem for _, i := range c.NodeSet { if i.GetNodeType() == tree.NtElem { n = i.(tree.Elem) } else { n = i.GetParent() } for n.GetNodeType() != tree.NtRoot { if attr, ok := tree.GetAttribute(n, "lang", tree.XMLSpace); ok { return checkLang(lStr, attr.Value), nil } n = n.GetParent() } } return tree.Bool(false), nil }
func rightNodeOperator(left tree.Result, right tree.NodeSet, f *xpFilt, op string) error { var err error for _, r := range right { rStr := r.ResValue() if eqOps[op] { err = equalsOperator(left, tree.String(rStr), f, op) if err == nil && f.ctx.String() == "true" { return nil } } else { err = numberOperator(left, tree.String(rStr), f, op) if err == nil && f.ctx.String() == "true" { return nil } } } f.ctx = tree.Bool(false) return nil }
func contains(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Bool(strings.Contains(args[0].String(), args[1].String())), nil }
func startsWith(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Bool(strings.Index(args[0].String(), args[1].String()) == 0), nil }
func _false(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Bool(false), nil }
func _true(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Bool(true), nil }