diff options
Diffstat (limited to 'qpid/cpp/src/qmf/Expression.cpp')
-rw-r--r-- | qpid/cpp/src/qmf/Expression.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/qpid/cpp/src/qmf/Expression.cpp b/qpid/cpp/src/qmf/Expression.cpp new file mode 100644 index 0000000000..7d48678c15 --- /dev/null +++ b/qpid/cpp/src/qmf/Expression.cpp @@ -0,0 +1,441 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "qmf/exceptions.h" +#include "qmf/Expression.h" +#include <iostream> + +using namespace std; +using namespace qmf; +using namespace qpid::types; + +Expression::Expression(const Variant::List& expr) +{ + static int level(0); + level++; + Variant::List::const_iterator iter(expr.begin()); + string op(iter->asString()); + iter++; + + if (op == "not") logicalOp = LOGICAL_NOT; + else if (op == "and") logicalOp = LOGICAL_AND; + else if (op == "or") logicalOp = LOGICAL_OR; + else { + logicalOp = LOGICAL_ID; + if (op == "eq") boolOp = BOOL_EQ; + else if (op == "ne") boolOp = BOOL_NE; + else if (op == "lt") boolOp = BOOL_LT; + else if (op == "le") boolOp = BOOL_LE; + else if (op == "gt") boolOp = BOOL_GT; + else if (op == "ge") boolOp = BOOL_GE; + else if (op == "re_match") boolOp = BOOL_RE_MATCH; + else if (op == "exists") boolOp = BOOL_EXISTS; + else if (op == "true") boolOp = BOOL_TRUE; + else if (op == "false") boolOp = BOOL_FALSE; + else + throw QmfException("Invalid operator in predicate expression"); + } + + if (logicalOp == LOGICAL_ID) { + switch (boolOp) { + case BOOL_EQ: + case BOOL_NE: + case BOOL_LT: + case BOOL_LE: + case BOOL_GT: + case BOOL_GE: + case BOOL_RE_MATCH: + // + // Binary operator: get two operands. + // + operandCount = 2; + break; + + case BOOL_EXISTS: + // + // Unary operator: get one operand. + // + operandCount = 1; + break; + + case BOOL_TRUE: + case BOOL_FALSE: + // + // Literal operator: no operands. + // + operandCount = 0; + break; + } + + for (int idx = 0; idx < operandCount; idx++) { + if (iter == expr.end()) + throw QmfException("Too few operands for operation: " + op); + if (iter->getType() == VAR_STRING) { + quoted[idx] = false; + operands[idx] = *iter; + } else if (iter->getType() == VAR_LIST) { + const Variant::List& sublist(iter->asList()); + Variant::List::const_iterator subIter(sublist.begin()); + if (subIter != sublist.end() && subIter->asString() == "quote") { + quoted[idx] = true; + subIter++; + if (subIter != sublist.end()) { + operands[idx] = *subIter; + subIter++; + if (subIter != sublist.end()) + throw QmfException("Extra tokens at end of 'quote'"); + } + } else + throw QmfException("Expected '[quote, <token>]'"); + } else + throw QmfException("Expected string or list as operand for: " + op); + iter++; + } + + if (iter != expr.end()) + throw QmfException("Too many operands for operation: " + op); + + } else { + // + // This is a logical expression, collect sub-expressions + // + while (iter != expr.end()) { + if (iter->getType() != VAR_LIST) + throw QmfException("Operands of " + op + " must be lists"); + expressionList.push_back(boost::shared_ptr<Expression>(new Expression(iter->asList()))); + iter++; + } + } + level--; +} + + +bool Expression::evaluate(const Variant::Map& data) const +{ + list<boost::shared_ptr<Expression> >::const_iterator iter; + + switch (logicalOp) { + case LOGICAL_ID: + return boolEval(data); + + case LOGICAL_NOT: + for (iter = expressionList.begin(); iter != expressionList.end(); iter++) + if ((*iter)->evaluate(data)) + return false; + return true; + + case LOGICAL_AND: + for (iter = expressionList.begin(); iter != expressionList.end(); iter++) + if (!(*iter)->evaluate(data)) + return false; + return true; + + case LOGICAL_OR: + for (iter = expressionList.begin(); iter != expressionList.end(); iter++) + if ((*iter)->evaluate(data)) + return true; + return false; + } + + return false; +} + + +bool Expression::boolEval(const Variant::Map& data) const +{ + Variant val[2]; + bool exists[2]; + + for (int idx = 0; idx < operandCount; idx++) { + if (quoted[idx]) { + exists[idx] = true; + val[idx] = operands[idx]; + } else { + Variant::Map::const_iterator mIter(data.find(operands[idx].asString())); + if (mIter == data.end()) { + exists[idx] = false; + } else { + exists[idx] = true; + val[idx] = mIter->second; + } + } + } + + switch (boolOp) { + case BOOL_EQ: return (exists[0] && exists[1] && (val[0].asString() == val[1].asString())); + case BOOL_NE: return (exists[0] && exists[1] && (val[0].asString() != val[1].asString())); + case BOOL_LT: return (exists[0] && exists[1] && lessThan(val[0], val[1])); + case BOOL_LE: return (exists[0] && exists[1] && lessEqual(val[0], val[1])); + case BOOL_GT: return (exists[0] && exists[1] && greaterThan(val[0], val[1])); + case BOOL_GE: return (exists[0] && exists[1] && greaterEqual(val[0], val[1])); + case BOOL_RE_MATCH: return false; // TODO + case BOOL_EXISTS: return exists[0]; + case BOOL_TRUE: return true; + case BOOL_FALSE: return false; + } + + return false; +} + +bool Expression::lessThan(const Variant& left, const Variant& right) const +{ + switch (left.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + return left.asInt64() < right.asInt64(); + case VAR_STRING: + try { + return left.asInt64() < right.asInt64(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_FLOAT: case VAR_DOUBLE: + switch (right.getType()) { + case VAR_FLOAT: case VAR_DOUBLE: + return left.asDouble() < right.asDouble(); + case VAR_STRING: + try { + return left.asDouble() < right.asDouble(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_STRING: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + try { + return left.asInt64() < right.asInt64(); + } catch (std::exception&) {} + break; + + case VAR_FLOAT: case VAR_DOUBLE: + try { + return left.asDouble() < right.asDouble(); + } catch (std::exception&) {} + break; + + case VAR_STRING: + return left.asString() < right.asString(); + default: + break; + } + default: + break; + } + + return false; +} + + +bool Expression::lessEqual(const Variant& left, const Variant& right) const +{ + switch (left.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + return left.asInt64() <= right.asInt64(); + case VAR_STRING: + try { + return left.asInt64() <= right.asInt64(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_FLOAT: case VAR_DOUBLE: + switch (right.getType()) { + case VAR_FLOAT: case VAR_DOUBLE: + return left.asDouble() <= right.asDouble(); + case VAR_STRING: + try { + return left.asDouble() <= right.asDouble(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_STRING: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + try { + return left.asInt64() <= right.asInt64(); + } catch (std::exception&) {} + break; + + case VAR_FLOAT: case VAR_DOUBLE: + try { + return left.asDouble() <= right.asDouble(); + } catch (std::exception&) {} + break; + + case VAR_STRING: + return left.asString() <= right.asString(); + default: + break; + } + default: + break; + } + + return false; +} + + +bool Expression::greaterThan(const Variant& left, const Variant& right) const +{ + switch (left.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + return left.asInt64() > right.asInt64(); + case VAR_STRING: + try { + return left.asInt64() > right.asInt64(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_FLOAT: case VAR_DOUBLE: + switch (right.getType()) { + case VAR_FLOAT: case VAR_DOUBLE: + return left.asDouble() > right.asDouble(); + case VAR_STRING: + try { + return left.asDouble() > right.asDouble(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_STRING: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + try { + return left.asInt64() > right.asInt64(); + } catch (std::exception&) {} + break; + + case VAR_FLOAT: case VAR_DOUBLE: + try { + return left.asDouble() > right.asDouble(); + } catch (std::exception&) {} + break; + + case VAR_STRING: + return left.asString() > right.asString(); + default: + break; + } + default: + break; + } + + return false; +} + + +bool Expression::greaterEqual(const Variant& left, const Variant& right) const +{ + switch (left.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + return left.asInt64() >= right.asInt64(); + case VAR_STRING: + try { + return left.asInt64() >= right.asInt64(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_FLOAT: case VAR_DOUBLE: + switch (right.getType()) { + case VAR_FLOAT: case VAR_DOUBLE: + return left.asDouble() >= right.asDouble(); + case VAR_STRING: + try { + return left.asDouble() >= right.asDouble(); + } catch (std::exception&) {} + break; + default: + break; + } + break; + + case VAR_STRING: + switch (right.getType()) { + case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: + case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: + try { + return left.asInt64() >= right.asInt64(); + } catch (std::exception&) {} + break; + + case VAR_FLOAT: case VAR_DOUBLE: + try { + return left.asDouble() >= right.asDouble(); + } catch (std::exception&) {} + break; + + case VAR_STRING: + return left.asString() >= right.asString(); + default: + break; + } + default: + break; + } + + return false; +} + + |