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 count(c tree.Ctx, args ...tree.Result) (tree.Result, error) { n, ok := args[0].(tree.NodeSet) if !ok { return nil, fmt.Errorf("Cannot convert object to a node-set") } return tree.Num(len(n)), nil }
func ceiling(c tree.Ctx, args ...tree.Result) (tree.Result, error) { n, ok := args[0].(tree.IsNum) if !ok { return nil, fmt.Errorf("Cannot convert object to a number") } return tree.Num(math.Ceil(float64(n.Num()))), nil }
func stringLength(c tree.Ctx, args ...tree.Result) (tree.Result, error) { var str string if len(args) == 1 { str = args[0].String() } else { str = c.NodeSet.String() } return tree.Num(len(str)), nil }
func round(c tree.Ctx, args ...tree.Result) (tree.Result, error) { isn, ok := args[0].(tree.IsNum) if !ok { return nil, fmt.Errorf("Cannot convert object to a number") } n := isn.Num() if math.IsNaN(float64(n)) || math.IsInf(float64(n), 0) { return n, nil } if n < -0.5 { n = tree.Num(int(n - 0.5)) } else if n > 0.5 { n = tree.Num(int(n + 0.5)) } else { n = 0 } return n, nil }
func sum(c tree.Ctx, args ...tree.Result) (tree.Result, error) { n, ok := args[0].(tree.NodeSet) if !ok { return nil, fmt.Errorf("Cannot convert object to a node-set") } ret := 0.0 for _, i := range n { ret += float64(tree.GetNodeNum(i)) } return tree.Num(ret), nil }
func substring(c tree.Ctx, args ...tree.Result) (tree.Result, error) { str := args[0].String() bNum, bErr := round(c, args[1]) if bErr != nil { return nil, bErr } b := bNum.(tree.Num).Num() if float64(b-1) >= float64(len(str)) || math.IsNaN(float64(b)) { return tree.String(""), nil } if len(args) == 2 { if b <= 1 { b = 1 } return tree.String(str[int(b)-1:]), nil } eNum, eErr := round(c, args[2]) if eErr != nil { return nil, eErr } e := eNum.(tree.Num).Num() if e <= 0 || math.IsNaN(float64(e)) || (math.IsInf(float64(b), 0) && math.IsInf(float64(e), 0)) { return tree.String(""), nil } if b <= 1 { e = b + e - 1 b = 1 } if float64(b+e-1) >= float64(len(str)) { e = tree.Num(len(str)) - b + 1 } return tree.String(str[int(b)-1 : int(b+e)-1]), nil }
func last(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Num(c.Size), nil }
func position(c tree.Ctx, args ...tree.Result) (tree.Result, error) { return tree.Num(c.Pos), nil }
func xfNumLit(f *xpFilt, val string) { num, _ := strconv.ParseFloat(val, 64) f.ctx = tree.Num(num) }