[Groonga-commit] groonga/grnxx at fe26755 [master] Add bitwise binary operators.

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index