susumu.yata
null+****@clear*****
Tue Jul 15 15:28:13 JST 2014
susumu.yata 2014-07-15 15:28:13 +0900 (Tue, 15 Jul 2014) New Revision: fe2675516481b3c0e9939f986c6f68e0a2b9249c https://github.com/groonga/grnxx/commit/fe2675516481b3c0e9939f986c6f68e0a2b9249c Message: Add bitwise binary operators. Modified files: include/grnxx/expression.hpp lib/grnxx/expression.cpp test/test_grnxx.cpp Modified: include/grnxx/expression.hpp (+41 -8) =================================================================== --- include/grnxx/expression.hpp 2014-07-15 13:57:59 +0900 (7e5961b) +++ include/grnxx/expression.hpp 2014-07-15 15:28:13 +0900 (d131315) @@ -10,21 +10,51 @@ namespace grnxx { enum OperatorType { // -- Unary operators -- +// LOGICAL_NOT_OPERATOR, // For Bool. + +// BITWISE_NOT_OPERATOR, // For Int. + +// POSITIVE_OPERATOR, // For Int, Float. +// NEGATIVE_OPERATOR, // For Int, Float. + + // Typecast operators. +// BOOL_OPERATOR, +// INT_OPERATOR, +// FLOAT_OPERATOR, +// TIME_OPERATOR, +// GEO_POINT_OPERATOR, +// TEXT_OPERATOR, + // -- Binary operators -- // Logical operators. - LOGICAL_AND_OPERATOR, - LOGICAL_OR_OPERATOR, + LOGICAL_AND_OPERATOR, // For Bool. + LOGICAL_OR_OPERATOR, // For Bool. // Equality operators. - EQUAL_OPERATOR, - NOT_EQUAL_OPERATOR, + EQUAL_OPERATOR, // For any types. + NOT_EQUAL_OPERATOR, // For any types. // Comparison operators. - LESS_OPERATOR, - LESS_EQUAL_OPERATOR, - GREATER_OPERATOR, - GREATER_EQUAL_OPERATOR + LESS_OPERATOR, // Int, Float, Time. + LESS_EQUAL_OPERATOR, // Int, Float, Time. + GREATER_OPERATOR, // Int, Float, Time. + GREATER_EQUAL_OPERATOR, // Int, Float, Time. + + // Bitwise operators. + BITWISE_AND_OPERATOR, // For Bool, Int. + BITWISE_OR_OPERATOR, // For Bool, Int. + BITWISE_XOR_OPERATOR, // For Bool, Int. + + // Arithmetic operators. +// PLUS_OPERATOR, // For Int, Float. +// MINUS_OPERATOR, // For Int, Float. +// DIVISION_OPERATOR, // For Int, Float. +// MULTIPLICATION_OPERATOR, // For Int, Float. +// MODULUS_OPERATOR, // For Int. + + // Array operators. +// SUBSCRIPT_OPERATOR, }; class Expression { @@ -140,6 +170,9 @@ class ExpressionBuilder { // Push an operator <, <=, >, or >=. template <typename T> bool push_comparison_operator(Error *error); + // Push an operator &, |, or ^. + template <typename T> + bool push_bitwise_operator(Error *error); }; } // namespace grnxx Modified: lib/grnxx/expression.cpp (+89 -1) =================================================================== --- lib/grnxx/expression.cpp 2014-07-15 13:57:59 +0900 (b133155) +++ lib/grnxx/expression.cpp 2014-07-15 15:28:13 +0900 (cbf4a51) @@ -310,8 +310,44 @@ struct GreaterEqual { }; }; +struct BitwiseAnd { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs & rhs; + }; + }; +}; + +struct BitwiseOr { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs | rhs; + }; + }; +}; + +struct BitwiseXor { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs ^ rhs; + }; + }; +}; + template <typename Op> -class BinaryNode : public Node<Bool> { +class BinaryNode : public Node<typename Op::Result> { public: using Arg1 = typename Op::Arg1; using Arg2 = typename Op::Arg2; @@ -522,6 +558,15 @@ bool ExpressionBuilder::push_operator(Error *error, case GREATER_EQUAL_OPERATOR: { return push_comparison_operator<GreaterEqual>(error); } + case BITWISE_AND_OPERATOR: { + return push_bitwise_operator<BitwiseAnd>(error); + } + case BITWISE_OR_OPERATOR: { + return push_bitwise_operator<BitwiseOr>(error); + } + case BITWISE_XOR_OPERATOR: { + return push_bitwise_operator<BitwiseXor>(error); + } default: { // TODO: Not supported yet. GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); @@ -684,4 +729,47 @@ bool ExpressionBuilder::push_comparison_operator(Error *error) { return true; } +template <typename T> +bool ExpressionBuilder::push_bitwise_operator(Error *error) { + if (stack_.size() < 2) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + auto &lhs = stack_[stack_.size() - 2]; + auto &rhs = stack_[stack_.size() - 1]; + if (lhs->data_type() != rhs->data_type()) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Type conflict"); + return false; + } + unique_ptr<ExpressionNode> node; + switch (lhs->data_type()) { + case BOOL_DATA: { + typename T::template Functor<Bool> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); + break; + } + case INT_DATA: { + typename T::template Functor<Int> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); + break; + } + // TODO: Support other comparable types. + default: { + GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.pop_back(); + stack_.back() = std::move(node); + return true; +} + } // namespace grnxx Modified: test/test_grnxx.cpp (+57 -0) =================================================================== --- test/test_grnxx.cpp 2014-07-15 13:57:59 +0900 (332e21e) +++ test/test_grnxx.cpp 2014-07-15 15:28:13 +0900 (9ad2dda) @@ -451,6 +451,63 @@ void test_expression() { assert(expression->filter(&error, &record_set)); assert(record_set.size() == 1); assert(record_set.get(0).row_id == 2); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read(&error, 2, &record_set) == 2); + + // ビット論理積を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(255))); + assert(builder->push_operator(&error, grnxx::BITWISE_AND_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Int(200))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 2); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read(&error, 2, &record_set) == 2); + + // ビット論理和を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(256))); + assert(builder->push_operator(&error, grnxx::BITWISE_OR_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Int(379))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 1); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read(&error, 2, &record_set) == 2); + + // ビット排他的論理和を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(255))); + assert(builder->push_operator(&error, grnxx::BITWISE_XOR_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Int(132))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 1); } } // namespace -------------- next part -------------- HTML����������������������������... Download