[Groonga-commit] groonga/grnxx at e22029a [master] Add arithmetic operators Plus, Minus, and Multiplication.

Back to archive index

susumu.yata null+****@clear*****
Tue Jul 22 15:40:28 JST 2014


susumu.yata	2014-07-22 15:40:28 +0900 (Tue, 22 Jul 2014)

  New Revision: e22029a9b5caef34052acfb3283323a52357555a
  https://github.com/groonga/grnxx/commit/e22029a9b5caef34052acfb3283323a52357555a

  Message:
    Add arithmetic operators Plus, Minus, and Multiplication.

  Modified files:
    include/grnxx/expression.hpp
    lib/grnxx/expression.cpp
    test/test_grnxx.cpp

  Modified: include/grnxx/expression.hpp (+6 -3)
===================================================================
--- include/grnxx/expression.hpp    2014-07-22 15:15:31 +0900 (99f5ea9)
+++ include/grnxx/expression.hpp    2014-07-22 15:40:28 +0900 (852bbd2)
@@ -47,10 +47,10 @@ enum OperatorType {
   BITWISE_XOR_OPERATOR,  // For Bool, Int.
 
   // Arithmetic operators.
-//  PLUS_OPERATOR,            // For Int, Float.
-//  MINUS_OPERATOR,           // For Int, Float.
+  PLUS_OPERATOR,            // For Int, Float.
+  MINUS_OPERATOR,           // For Int, Float.
+  MULTIPLICATION_OPERATOR,  // For Int, Float.
 //  DIVISION_OPERATOR,        // For Int, Float.
-//  MULTIPLICATION_OPERATOR,  // For Int, Float.
 //  MODULUS_OPERATOR,         // For Int.
 
   // Array operators.
@@ -174,6 +174,9 @@ class ExpressionBuilder {
   // Push an operator &, |, or ^.
   template <typename T>
   bool push_bitwise_operator(Error *error);
+  // Push an operator +, -, or *.
+  template <typename T>
+  bool push_arithmetic_operator(Error *error);
 };
 
 }  // namespace grnxx

  Modified: lib/grnxx/expression.cpp (+87 -0)
===================================================================
--- lib/grnxx/expression.cpp    2014-07-22 15:15:31 +0900 (79feb98)
+++ lib/grnxx/expression.cpp    2014-07-22 15:40:28 +0900 (1f100e5)
@@ -357,6 +357,42 @@ struct BitwiseXor {
   };
 };
 
+struct Plus {
+  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 Minus {
+  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 Multiplication {
+  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<typename Op::Result> {
  public:
@@ -778,6 +814,15 @@ bool ExpressionBuilder::push_operator(Error *error,
     case BITWISE_XOR_OPERATOR: {
       return push_bitwise_operator<BitwiseXor>(error);
     }
+    case PLUS_OPERATOR: {
+      return push_arithmetic_operator<Plus>(error);
+    }
+    case MINUS_OPERATOR: {
+      return push_arithmetic_operator<Minus>(error);
+    }
+    case MULTIPLICATION_OPERATOR: {
+      return push_arithmetic_operator<Multiplication>(error);
+    }
     default: {
       // TODO: Not supported yet.
       GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet");
@@ -1018,4 +1063,46 @@ bool ExpressionBuilder::push_bitwise_operator(Error *error) {
   return true;
 }
 
+template <typename T>
+bool ExpressionBuilder::push_arithmetic_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 INT_DATA: {
+      typename T::template Functor<Int> functor;
+      node.reset(new (nothrow) BinaryNode<decltype(functor)>(
+          functor, std::move(lhs), std::move(rhs)));
+      break;
+    }
+    case FLOAT_DATA: {
+      typename T::template Functor<Float> functor;
+      node.reset(new (nothrow) BinaryNode<decltype(functor)>(
+          functor, std::move(lhs), std::move(rhs)));
+      break;
+    }
+    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-22 15:15:31 +0900 (0143542)
+++ test/test_grnxx.cpp    2014-07-22 15:40:28 +0900 (b82c2ba)
@@ -661,6 +661,63 @@ void test_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_all(&error, &record_set) == 2);
+
+  // 加算を試す.
+  assert(builder->push_column(&error, "IntColumn"));
+  assert(builder->push_datum(&error, grnxx::Int(100)));
+  assert(builder->push_operator(&error, grnxx::PLUS_OPERATOR));
+  assert(builder->push_datum(&error, grnxx::Int(223)));
+  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_all(&error, &record_set) == 2);
+
+  // 減算を試す.
+  assert(builder->push_column(&error, "FloatColumn"));
+  assert(builder->push_datum(&error, grnxx::Float(0.25)));
+  assert(builder->push_operator(&error, grnxx::MINUS_OPERATOR));
+  assert(builder->push_datum(&error, grnxx::Float(0.0)));
+  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_all(&error, &record_set) == 2);
+
+  // 乗算を試す.
+  assert(builder->push_column(&error, "IntColumn"));
+  assert(builder->push_datum(&error, grnxx::Int(2)));
+  assert(builder->push_operator(&error, grnxx::MULTIPLICATION_OPERATOR));
+  assert(builder->push_datum(&error, grnxx::Int(912)));
+  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);
 }
 
 }  // namespace
-------------- next part --------------
HTML����������������������������...
Download 



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