You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ap...@apache.org on 2019/02/20 20:03:55 UTC

[arrow] branch master updated: ARROW-4615: [C++] Add checked_pointer_cast

This is an automated email from the ASF dual-hosted git repository.

apitrou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 3173b0d  ARROW-4615: [C++] Add checked_pointer_cast
3173b0d is described below

commit 3173b0ddad133681aedb6e5bca35e8df897f8a31
Author: Korn, Uwe <Uw...@blue-yonder.com>
AuthorDate: Wed Feb 20 21:03:43 2019 +0100

    ARROW-4615: [C++] Add checked_pointer_cast
    
    Author: Korn, Uwe <Uw...@blue-yonder.com>
    Author: Uwe L. Korn <uw...@xhochy.com>
    
    Closes #3690 from xhochy/ARROW-4615 and squashes the following commits:
    
    175647016 <Korn, Uwe> docker-compose run clang-format
    f245b1f6f <Korn, Uwe> Decimal is also a fixed size binary
    cdd203ce7 <Korn, Uwe> Keep dynamic_cast in tests
    5f5d2bbdb <Korn, Uwe> Don't rely on RTTI
    2d1560a69 <Korn, Uwe> Fix merge issue
    69ac1df44 <Uwe L. Korn> ARROW-4615:  Add checked_pointer_cast
---
 cpp/src/arrow/compare.cc              |  6 +++---
 cpp/src/arrow/compute/kernels/cast.cc |  4 +---
 cpp/src/arrow/ipc/reader.cc           |  6 ++++--
 cpp/src/arrow/table.cc                |  5 ++++-
 cpp/src/arrow/type_traits.h           | 15 +++++++++++++++
 cpp/src/arrow/util/checked_cast.h     | 10 ++++++++++
 6 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/cpp/src/arrow/compare.cc b/cpp/src/arrow/compare.cc
index 1147529..8c8958f 100644
--- a/cpp/src/arrow/compare.cc
+++ b/cpp/src/arrow/compare.cc
@@ -311,7 +311,7 @@ class RangeEqualsVisitor {
 };
 
 static bool IsEqualPrimitive(const PrimitiveArray& left, const PrimitiveArray& right) {
-  const auto& size_meta = dynamic_cast<const FixedWidthType&>(*left.type());
+  const auto& size_meta = checked_cast<const FixedWidthType&>(*left.type());
   const int byte_width = size_meta.bit_width() / CHAR_BIT;
 
   const uint8_t* left_data = nullptr;
@@ -769,7 +769,7 @@ bool TensorEquals(const Tensor& left, const Tensor& right) {
             StridedTensorContentEquals(0, 0, 0, type.bit_width() / 8, left, right);
       }
     } else {
-      const auto& size_meta = dynamic_cast<const FixedWidthType&>(*left.type());
+      const auto& size_meta = checked_cast<const FixedWidthType&>(*left.type());
       const int byte_width = size_meta.bit_width() / CHAR_BIT;
       DCHECK_GT(byte_width, 0);
 
@@ -809,7 +809,7 @@ struct SparseTensorEqualsImpl<SparseIndexType, SparseIndexType> {
       return false;
     }
 
-    const auto& size_meta = dynamic_cast<const FixedWidthType&>(*left.type());
+    const auto& size_meta = checked_cast<const FixedWidthType&>(*left.type());
     const int byte_width = size_meta.bit_width() / CHAR_BIT;
     DCHECK_GT(byte_width, 0);
 
diff --git a/cpp/src/arrow/compute/kernels/cast.cc b/cpp/src/arrow/compute/kernels/cast.cc
index 5ddc59f..97601b5 100644
--- a/cpp/src/arrow/compute/kernels/cast.cc
+++ b/cpp/src/arrow/compute/kernels/cast.cc
@@ -627,9 +627,7 @@ class CastKernelBase : public UnaryKernel {
   std::shared_ptr<DataType> out_type_;
 };
 
-bool NeedToPreallocate(const DataType& type) {
-  return dynamic_cast<const FixedWidthType*>(&type) != nullptr;
-}
+bool NeedToPreallocate(const DataType& type) { return is_fixed_width(type.id()); }
 
 Status InvokeWithAllocation(FunctionContext* ctx, UnaryKernel* func, const Datum& input,
                             Datum* out) {
diff --git a/cpp/src/arrow/ipc/reader.cc b/cpp/src/arrow/ipc/reader.cc
index 1f04fad..0aba454 100644
--- a/cpp/src/arrow/ipc/reader.cc
+++ b/cpp/src/arrow/ipc/reader.cc
@@ -45,6 +45,8 @@
 #include "arrow/util/logging.h"
 #include "arrow/visitor_inline.h"
 
+using arrow::internal::checked_pointer_cast;
+
 namespace arrow {
 
 namespace flatbuf = org::apache::arrow::flatbuf;
@@ -823,14 +825,14 @@ Status ReadSparseTensor(const Buffer& metadata, io::RandomAccessFile* file,
       RETURN_NOT_OK(ReadSparseCOOIndex(sparse_tensor, shape.size(), non_zero_length, file,
                                        &sparse_index));
       return MakeSparseTensorWithSparseCOOIndex(
-          type, shape, dim_names, std::dynamic_pointer_cast<SparseCOOIndex>(sparse_index),
+          type, shape, dim_names, checked_pointer_cast<SparseCOOIndex>(sparse_index),
           non_zero_length, data, out);
 
     case SparseTensorFormat::CSR:
       RETURN_NOT_OK(ReadSparseCSRIndex(sparse_tensor, shape.size(), non_zero_length, file,
                                        &sparse_index));
       return MakeSparseTensorWithSparseCSRIndex(
-          type, shape, dim_names, std::dynamic_pointer_cast<SparseCSRIndex>(sparse_index),
+          type, shape, dim_names, checked_pointer_cast<SparseCSRIndex>(sparse_index),
           non_zero_length, data, out);
 
     default:
diff --git a/cpp/src/arrow/table.cc b/cpp/src/arrow/table.cc
index d232ac3..aed06e0 100644
--- a/cpp/src/arrow/table.cc
+++ b/cpp/src/arrow/table.cc
@@ -28,11 +28,14 @@
 #include "arrow/record_batch.h"
 #include "arrow/status.h"
 #include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
 #include "arrow/util/logging.h"
 #include "arrow/util/stl.h"
 
 namespace arrow {
 
+using internal::checked_cast;
+
 // ----------------------------------------------------------------------
 // ChunkedArray and Column methods
 
@@ -154,7 +157,7 @@ Status ChunkedArray::Flatten(MemoryPool* pool,
   std::vector<ArrayVector> flattened_chunks;
   for (const auto& chunk : chunks_) {
     ArrayVector res;
-    RETURN_NOT_OK(dynamic_cast<const StructArray&>(*chunk).Flatten(pool, &res));
+    RETURN_NOT_OK(checked_cast<const StructArray&>(*chunk).Flatten(pool, &res));
     if (!flattened_chunks.size()) {
       // First chunk
       for (const auto& array : res) {
diff --git a/cpp/src/arrow/type_traits.h b/cpp/src/arrow/type_traits.h
index 51cf5ec..ca16e15 100644
--- a/cpp/src/arrow/type_traits.h
+++ b/cpp/src/arrow/type_traits.h
@@ -486,6 +486,21 @@ static inline bool is_dictionary(Type::type type_id) {
   return type_id == Type::DICTIONARY;
 }
 
+static inline bool is_fixed_size_binary(Type::type type_id) {
+  switch (type_id) {
+    case Type::DECIMAL:
+    case Type::FIXED_SIZE_BINARY:
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
+static inline bool is_fixed_width(Type::type type_id) {
+  return is_primitive(type_id) || is_dictionary(type_id) || is_fixed_size_binary(type_id);
+}
+
 }  // namespace arrow
 
 #endif  // ARROW_TYPE_TRAITS_H
diff --git a/cpp/src/arrow/util/checked_cast.h b/cpp/src/arrow/util/checked_cast.h
index 33cc041..718f105 100644
--- a/cpp/src/arrow/util/checked_cast.h
+++ b/cpp/src/arrow/util/checked_cast.h
@@ -18,6 +18,7 @@
 #ifndef ARROW_CAST_H
 #define ARROW_CAST_H
 
+#include <memory>
 #include <type_traits>
 
 namespace arrow {
@@ -38,6 +39,15 @@ inline OutputType checked_cast(InputType&& value) {
 #endif
 }
 
+template <class T, class U>
+std::shared_ptr<T> checked_pointer_cast(const std::shared_ptr<U>& r) noexcept {
+#ifndef NDEBUG
+  return std::static_pointer_cast<T>(r);
+#else
+  return std::dynamic_pointer_cast<T>(r);
+#endif
+}
+
 }  // namespace internal
 }  // namespace arrow