diff --git a/src/command_ui.cc b/src/command_ui.cc index 5cd1e4af..c98f9427 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -546,24 +546,30 @@ as_vector(const torrent::Object::list_type& args) { } int64_t -apply_math_basic(const std::function op, const torrent::Object::list_type& args) { - if (args.size() == 0) - throw torrent::input_error("Wrong argument count in apply_math_basic."); +apply_math_basic(const char* name, const std::function op, const torrent::Object::list_type& args) { + int64_t val = 0, rhs = 0; + bool divides = !strcmp(name, "math.div") || !strcmp(name, "math.mod"); - int64_t val = 0; + if (args.size() == 0) + throw torrent::input_error(std::string(name) + ": No arguments provided!"); for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { if (itr->is_value()) { - val = itr == args.begin() ? itr->as_value() : op(val, itr->as_value()); + rhs = itr->as_value(); } else if (itr->is_string()) { - val = itr == args.begin() ? rpc::convert_to_value(itr->as_string()) : op(val, rpc::convert_to_value(itr->as_string())); + rhs = rpc::convert_to_value(itr->as_string()); } else if (itr->is_list()) { - val = itr == args.begin() ? apply_math_basic(op, itr->as_list()) : op(val, apply_math_basic(op, itr->as_list())); + rhs = apply_math_basic(name, op, itr->as_list()); } else { - throw torrent::input_error("Wrong type supplied to apply_math_basic."); + throw torrent::input_error(std::string(name) + ": Wrong argument type"); } + if (divides && !rhs && itr != args.begin()) + throw torrent::input_error(std::string(name) + ": Division by zero!"); + + val = itr == args.begin() ? rhs : op(val, rhs); + } return val; @@ -626,9 +632,9 @@ apply_arith_other(const char* op, const torrent::Object::list_type& args) { if (args.size() == 0) throw torrent::input_error("Wrong argument count in apply_arith_other."); - if (op == "average") { - return (int64_t)(apply_math_basic(std::plus(), args) / apply_arith_count(args)); - } else if (op == "median") { + if (strcmp(op, "average") == 0) { + return (int64_t)(apply_math_basic(op, std::plus(), args) / apply_arith_count(args)); + } else if (strcmp(op, "median") == 0) { std::vector result = as_vector(args); return (int64_t)rak::median(result.begin(), result.end()); } else { @@ -702,11 +708,11 @@ initialize_command_ui() { CMD2_ANY_VALUE("convert.xb", std::bind(&apply_to_xb, std::placeholders::_2)); CMD2_ANY_VALUE("convert.throttle", std::bind(&apply_to_throttle, std::placeholders::_2)); - CMD2_ANY_LIST("math.add", std::bind(&apply_math_basic, std::plus(), std::placeholders::_2)); - CMD2_ANY_LIST("math.sub", std::bind(&apply_math_basic, std::minus(), std::placeholders::_2)); - CMD2_ANY_LIST("math.mul", std::bind(&apply_math_basic, std::multiplies(), std::placeholders::_2)); - CMD2_ANY_LIST("math.div", std::bind(&apply_math_basic, std::divides(), std::placeholders::_2)); - CMD2_ANY_LIST("math.mod", std::bind(&apply_math_basic, std::modulus(), std::placeholders::_2)); + CMD2_ANY_LIST("math.add", std::bind(&apply_math_basic, "math.add", std::plus(), std::placeholders::_2)); + CMD2_ANY_LIST("math.sub", std::bind(&apply_math_basic, "math.sub", std::minus(), std::placeholders::_2)); + CMD2_ANY_LIST("math.mul", std::bind(&apply_math_basic, "math.mul", std::multiplies(), std::placeholders::_2)); + CMD2_ANY_LIST("math.div", std::bind(&apply_math_basic, "math.div", std::divides(), std::placeholders::_2)); + CMD2_ANY_LIST("math.mod", std::bind(&apply_math_basic, "math.mod", std::modulus(), std::placeholders::_2)); CMD2_ANY_LIST("math.min", std::bind(&apply_arith_basic, std::less(), std::placeholders::_2)); CMD2_ANY_LIST("math.max", std::bind(&apply_arith_basic, std::greater(), std::placeholders::_2)); CMD2_ANY_LIST("math.cnt", std::bind(&apply_arith_count, std::placeholders::_2));