You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by uw...@apache.org on 2018/05/04 08:21:21 UTC
[arrow] branch master updated: ARROW-2478: [C++] Introduce a
checked_cast function that performs a dynamic_cast in debug mode
This is an automated email from the ASF dual-hosted git repository.
uwe 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 73f0d8e ARROW-2478: [C++] Introduce a checked_cast function that performs a dynamic_cast in debug mode
73f0d8e is described below
commit 73f0d8e92f1e23f0e0c36910e96f25729d24f259
Author: Phillip Cloud <cp...@gmail.com>
AuthorDate: Fri May 4 10:21:14 2018 +0200
ARROW-2478: [C++] Introduce a checked_cast function that performs a dynamic_cast in debug mode
Author: Phillip Cloud <cp...@gmail.com>
Closes #1937 from cpcloud/ARROW-2478 and squashes the following commits:
afa88af2 <Phillip Cloud> ARROW-2478: Introduce a checked_cast function that performs a dynamic_cast in debug mode
---
cpp/src/arrow/adapters/orc/adapter.cc | 47 ++++++++---------
cpp/src/arrow/array-test.cc | 71 +++++++++++++-------------
cpp/src/arrow/array.cc | 23 +++++----
cpp/src/arrow/array.h | 5 +-
cpp/src/arrow/builder.cc | 15 +++---
cpp/src/arrow/compare.cc | 49 +++++++++---------
cpp/src/arrow/compute/kernels/cast.cc | 33 ++++++------
cpp/src/arrow/compute/kernels/hash.cc | 15 +++---
cpp/src/arrow/io/io-memory-test.cc | 3 +-
cpp/src/arrow/ipc/feather-test.cc | 3 +-
cpp/src/arrow/ipc/feather.cc | 13 ++---
cpp/src/arrow/ipc/ipc-read-write-test.cc | 9 ++--
cpp/src/arrow/ipc/json-internal.cc | 11 ++--
cpp/src/arrow/ipc/metadata-internal.cc | 19 +++----
cpp/src/arrow/ipc/writer.cc | 9 ++--
cpp/src/arrow/pretty_print.cc | 3 +-
cpp/src/arrow/python/arrow_to_pandas.cc | 59 ++++++++++-----------
cpp/src/arrow/python/arrow_to_python.cc | 33 ++++++------
cpp/src/arrow/python/builtin_convert.cc | 31 ++++++-----
cpp/src/arrow/python/helpers.cc | 3 +-
cpp/src/arrow/python/numpy_to_arrow.cc | 25 ++++-----
cpp/src/arrow/python/python-test.cc | 13 ++---
cpp/src/arrow/status.cc | 2 +-
cpp/src/arrow/table_builder-test.cc | 5 +-
cpp/src/arrow/table_builder.h | 3 +-
cpp/src/arrow/tensor.cc | 7 +--
cpp/src/arrow/type-test.cc | 5 +-
cpp/src/arrow/type.cc | 3 +-
cpp/src/arrow/type.h | 3 +-
cpp/src/arrow/util/CMakeLists.txt | 1 +
cpp/src/arrow/util/checked-cast-test.cc | 71 ++++++++++++++++++++++++++
cpp/src/arrow/util/{hash.cc => checked_cast.h} | 32 +++++++-----
cpp/src/arrow/util/hash.cc | 2 +-
cpp/src/arrow/visitor_inline.h | 5 +-
python/pyarrow/tests/pandas_examples.py | 4 +-
35 files changed, 371 insertions(+), 264 deletions(-)
diff --git a/cpp/src/arrow/adapters/orc/adapter.cc b/cpp/src/arrow/adapters/orc/adapter.cc
index 527b9e9..7350f79 100644
--- a/cpp/src/arrow/adapters/orc/adapter.cc
+++ b/cpp/src/arrow/adapters/orc/adapter.cc
@@ -37,6 +37,7 @@
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/macros.h"
#include "arrow/util/visibility.h"
@@ -360,7 +361,7 @@ class ORCFileReader::Impl {
RETURN_NOT_OK(RecordBatchBuilder::Make(schema, pool_, nrows, &builder));
// The top-level type must be a struct to read into an arrow table
- const auto& struct_batch = static_cast<liborc::StructVectorBatch&>(*batch);
+ const auto& struct_batch = checked_cast<liborc::StructVectorBatch&>(*batch);
while (rowreader->next(*batch)) {
for (int i = 0; i < builder->num_fields(); i++) {
@@ -428,8 +429,8 @@ class ORCFileReader::Impl {
Status AppendStructBatch(const liborc::Type* type, liborc::ColumnVectorBatch* cbatch,
int64_t offset, int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<StructBuilder*>(abuilder);
- auto batch = static_cast<liborc::StructVectorBatch*>(cbatch);
+ auto builder = checked_cast<StructBuilder*>(abuilder);
+ auto batch = checked_cast<liborc::StructVectorBatch*>(cbatch);
const uint8_t* valid_bytes = nullptr;
if (batch->hasNulls) {
@@ -446,8 +447,8 @@ class ORCFileReader::Impl {
Status AppendListBatch(const liborc::Type* type, liborc::ColumnVectorBatch* cbatch,
int64_t offset, int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<ListBuilder*>(abuilder);
- auto batch = static_cast<liborc::ListVectorBatch*>(cbatch);
+ auto builder = checked_cast<ListBuilder*>(abuilder);
+ auto batch = checked_cast<liborc::ListVectorBatch*>(cbatch);
liborc::ColumnVectorBatch* elements = batch->elements.get();
const liborc::Type* elemtype = type->getSubtype(0);
@@ -468,9 +469,9 @@ class ORCFileReader::Impl {
Status AppendMapBatch(const liborc::Type* type, liborc::ColumnVectorBatch* cbatch,
int64_t offset, int64_t length, ArrayBuilder* abuilder) {
- auto list_builder = static_cast<ListBuilder*>(abuilder);
- auto struct_builder = static_cast<StructBuilder*>(list_builder->value_builder());
- auto batch = static_cast<liborc::MapVectorBatch*>(cbatch);
+ auto list_builder = checked_cast<ListBuilder*>(abuilder);
+ auto struct_builder = checked_cast<StructBuilder*>(list_builder->value_builder());
+ auto batch = checked_cast<liborc::MapVectorBatch*>(cbatch);
liborc::ColumnVectorBatch* keys = batch->keys.get();
liborc::ColumnVectorBatch* vals = batch->elements.get();
const liborc::Type* keytype = type->getSubtype(0);
@@ -495,8 +496,8 @@ class ORCFileReader::Impl {
template <class builder_type, class batch_type, class elem_type>
Status AppendNumericBatch(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<builder_type*>(abuilder);
- auto batch = static_cast<batch_type*>(cbatch);
+ auto builder = checked_cast<builder_type*>(abuilder);
+ auto batch = checked_cast<batch_type*>(cbatch);
if (length == 0) {
return Status::OK();
@@ -513,8 +514,8 @@ class ORCFileReader::Impl {
template <class builder_type, class target_type, class batch_type, class source_type>
Status AppendNumericBatchCast(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<builder_type*>(abuilder);
- auto batch = static_cast<batch_type*>(cbatch);
+ auto builder = checked_cast<builder_type*>(abuilder);
+ auto batch = checked_cast<batch_type*>(cbatch);
if (length == 0) {
return Status::OK();
@@ -537,8 +538,8 @@ class ORCFileReader::Impl {
Status AppendBoolBatch(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<BooleanBuilder*>(abuilder);
- auto batch = static_cast<liborc::LongVectorBatch*>(cbatch);
+ auto builder = checked_cast<BooleanBuilder*>(abuilder);
+ auto batch = checked_cast<liborc::LongVectorBatch*>(cbatch);
if (length == 0) {
return Status::OK();
@@ -566,8 +567,8 @@ class ORCFileReader::Impl {
Status AppendTimestampBatch(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<TimestampBuilder*>(abuilder);
- auto batch = static_cast<liborc::TimestampVectorBatch*>(cbatch);
+ auto builder = checked_cast<TimestampBuilder*>(abuilder);
+ auto batch = checked_cast<liborc::TimestampVectorBatch*>(cbatch);
if (length == 0) {
return Status::OK();
@@ -595,8 +596,8 @@ class ORCFileReader::Impl {
template <class builder_type>
Status AppendBinaryBatch(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<builder_type*>(abuilder);
- auto batch = static_cast<liborc::StringVectorBatch*>(cbatch);
+ auto builder = checked_cast<builder_type*>(abuilder);
+ auto batch = checked_cast<liborc::StringVectorBatch*>(cbatch);
const bool has_nulls = batch->hasNulls;
for (int64_t i = offset; i < length + offset; i++) {
@@ -612,8 +613,8 @@ class ORCFileReader::Impl {
Status AppendFixedBinaryBatch(liborc::ColumnVectorBatch* cbatch, int64_t offset,
int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<FixedSizeBinaryBuilder*>(abuilder);
- auto batch = static_cast<liborc::StringVectorBatch*>(cbatch);
+ auto builder = checked_cast<FixedSizeBinaryBuilder*>(abuilder);
+ auto batch = checked_cast<liborc::StringVectorBatch*>(cbatch);
const bool has_nulls = batch->hasNulls;
for (int64_t i = offset; i < length + offset; i++) {
@@ -628,11 +629,11 @@ class ORCFileReader::Impl {
Status AppendDecimalBatch(const liborc::Type* type, liborc::ColumnVectorBatch* cbatch,
int64_t offset, int64_t length, ArrayBuilder* abuilder) {
- auto builder = static_cast<Decimal128Builder*>(abuilder);
+ auto builder = checked_cast<Decimal128Builder*>(abuilder);
const bool has_nulls = cbatch->hasNulls;
if (type->getPrecision() == 0 || type->getPrecision() > 18) {
- auto batch = static_cast<liborc::Decimal128VectorBatch*>(cbatch);
+ auto batch = checked_cast<liborc::Decimal128VectorBatch*>(cbatch);
for (int64_t i = offset; i < length + offset; i++) {
if (!has_nulls || batch->notNull[i]) {
RETURN_NOT_OK(builder->Append(
@@ -642,7 +643,7 @@ class ORCFileReader::Impl {
}
}
} else {
- auto batch = static_cast<liborc::Decimal64VectorBatch*>(cbatch);
+ auto batch = checked_cast<liborc::Decimal64VectorBatch*>(cbatch);
for (int64_t i = offset; i < length + offset; i++) {
if (!has_nulls || batch->notNull[i]) {
RETURN_NOT_OK(builder->Append(Decimal128(batch->values[i])));
diff --git a/cpp/src/arrow/array-test.cc b/cpp/src/arrow/array-test.cc
index 60ed291..0095832 100644
--- a/cpp/src/arrow/array-test.cc
+++ b/cpp/src/arrow/array-test.cc
@@ -33,6 +33,7 @@
#include "arrow/test-util.h"
#include "arrow/type.h"
#include "arrow/type_traits.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
namespace arrow {
@@ -223,10 +224,10 @@ class TestPrimitiveBuilder : public TestBuilder {
std::unique_ptr<ArrayBuilder> tmp;
ASSERT_OK(MakeBuilder(pool_, type_, &tmp));
- builder_.reset(static_cast<BuilderType*>(tmp.release()));
+ builder_.reset(checked_cast<BuilderType*>(tmp.release()));
ASSERT_OK(MakeBuilder(pool_, type_, &tmp));
- builder_nn_.reset(static_cast<BuilderType*>(tmp.release()));
+ builder_nn_.reset(checked_cast<BuilderType*>(tmp.release()));
}
void RandomData(int64_t N, double pct_null = 0.1) {
@@ -733,8 +734,8 @@ TEST(TestBooleanBuilder, TestStdBoolVectorAppend) {
ASSERT_OK(builder.Finish(&result));
ASSERT_OK(builder_nn.Finish(&result_nn));
- const auto& arr = static_cast<const BooleanArray&>(*result);
- const auto& arr_nn = static_cast<const BooleanArray&>(*result_nn);
+ const auto& arr = checked_cast<const BooleanArray&>(*result);
+ const auto& arr_nn = checked_cast<const BooleanArray&>(*result_nn);
for (int i = 0; i < length; ++i) {
if (is_valid[i]) {
ASSERT_FALSE(arr.IsNull(i));
@@ -897,9 +898,9 @@ TEST_F(TestStringArray, CompareNullByteSlots) {
ASSERT_OK(builder2.Finish(&array2));
ASSERT_OK(builder3.Finish(&array3));
- const auto& a1 = static_cast<const StringArray&>(*array);
- const auto& a2 = static_cast<const StringArray&>(*array2);
- const auto& a3 = static_cast<const StringArray&>(*array3);
+ const auto& a1 = checked_cast<const StringArray&>(*array);
+ const auto& a2 = checked_cast<const StringArray&>(*array2);
+ const auto& a3 = checked_cast<const StringArray&>(*array3);
// The validity bitmaps are the same, the data is different, but the unequal
// portion is masked out
@@ -1198,7 +1199,7 @@ TEST_F(TestBinaryArray, TestEqualsEmptyStrings) {
std::shared_ptr<Array> left_arr;
ASSERT_OK(builder.Finish(&left_arr));
- const BinaryArray& left = static_cast<const BinaryArray&>(*left_arr);
+ const BinaryArray& left = checked_cast<const BinaryArray&>(*left_arr);
std::shared_ptr<Array> right =
std::make_shared<BinaryArray>(left.length(), left.value_offsets(), nullptr,
left.null_bitmap(), left.null_count());
@@ -1396,7 +1397,7 @@ TEST_F(TestFWBinaryArray, Builder) {
auto CheckResult = [&length, &is_valid, &raw_data, &byte_width](const Array& result) {
// Verify output
- const auto& fw_result = static_cast<const FixedSizeBinaryArray&>(result);
+ const auto& fw_result = checked_cast<const FixedSizeBinaryArray&>(result);
ASSERT_EQ(length, result.length());
@@ -1466,8 +1467,8 @@ TEST_F(TestFWBinaryArray, EqualsRangeEquals) {
ASSERT_OK(builder1.Finish(&array1));
ASSERT_OK(builder2.Finish(&array2));
- const auto& a1 = static_cast<const FixedSizeBinaryArray&>(*array1);
- const auto& a2 = static_cast<const FixedSizeBinaryArray&>(*array2);
+ const auto& a1 = checked_cast<const FixedSizeBinaryArray&>(*array1);
+ const auto& a2 = checked_cast<const FixedSizeBinaryArray&>(*array2);
FixedSizeBinaryArray equal1(type, 2, a1.values(), a1.null_bitmap(), 1);
FixedSizeBinaryArray equal2(type, 2, a2.values(), a1.null_bitmap(), 1);
@@ -1490,7 +1491,7 @@ TEST_F(TestFWBinaryArray, ZeroSize) {
std::shared_ptr<Array> array;
ASSERT_OK(builder.Finish(&array));
- const auto& fw_array = static_cast<const FixedSizeBinaryArray&>(*array);
+ const auto& fw_array = checked_cast<const FixedSizeBinaryArray&>(*array);
// data is never allocated
ASSERT_TRUE(fw_array.values() == nullptr);
@@ -2473,7 +2474,7 @@ class TestListArray : public TestBuilder {
std::unique_ptr<ArrayBuilder> tmp;
ASSERT_OK(MakeBuilder(pool_, type_, &tmp));
- builder_.reset(static_cast<ListBuilder*>(tmp.release()));
+ builder_.reset(checked_cast<ListBuilder*>(tmp.release()));
}
void Done() {
@@ -2490,7 +2491,7 @@ class TestListArray : public TestBuilder {
};
TEST_F(TestListArray, Equality) {
- Int32Builder* vb = static_cast<Int32Builder*>(builder_->value_builder());
+ Int32Builder* vb = checked_cast<Int32Builder*>(builder_->value_builder());
std::shared_ptr<Array> array, equal_array, unequal_array;
vector<int32_t> equal_offsets = {0, 1, 2, 5, 6, 7, 8, 10};
@@ -2654,7 +2655,7 @@ TEST_F(TestListArray, TestBasics) {
vector<int> lengths = {3, 0, 4};
vector<uint8_t> is_valid = {1, 0, 1};
- Int32Builder* vb = static_cast<Int32Builder*>(builder_->value_builder());
+ Int32Builder* vb = checked_cast<Int32Builder*>(builder_->value_builder());
ASSERT_OK(builder_->Reserve(lengths.size()));
ASSERT_OK(vb->Reserve(values.size()));
@@ -2677,7 +2678,7 @@ TEST_F(TestListArray, BulkAppend) {
vector<uint8_t> is_valid = {1, 0, 1};
vector<int32_t> offsets = {0, 3, 3};
- Int32Builder* vb = static_cast<Int32Builder*>(builder_->value_builder());
+ Int32Builder* vb = checked_cast<Int32Builder*>(builder_->value_builder());
ASSERT_OK(vb->Reserve(values.size()));
ASSERT_OK(builder_->AppendValues(offsets.data(), offsets.size(), is_valid.data()));
@@ -2695,7 +2696,7 @@ TEST_F(TestListArray, BulkAppendInvalid) {
vector<uint8_t> is_valid = {1, 0, 1};
vector<int32_t> offsets = {0, 2, 4}; // should be 0, 3, 3 given the is_null array
- Int32Builder* vb = static_cast<Int32Builder*>(builder_->value_builder());
+ Int32Builder* vb = checked_cast<Int32Builder*>(builder_->value_builder());
ASSERT_OK(vb->Reserve(values.size()));
ASSERT_OK(builder_->AppendValues(offsets.data(), offsets.size(), is_valid.data()));
@@ -2928,7 +2929,7 @@ class TestStructBuilder : public TestBuilder {
std::unique_ptr<ArrayBuilder> tmp;
ASSERT_OK(MakeBuilder(pool_, type_, &tmp));
- builder_.reset(static_cast<StructBuilder*>(tmp.release()));
+ builder_.reset(checked_cast<StructBuilder*>(tmp.release()));
ASSERT_EQ(2, static_cast<int>(builder_->num_fields()));
}
@@ -2950,12 +2951,12 @@ TEST_F(TestStructBuilder, TestAppendNull) {
ASSERT_OK(builder_->AppendNull());
ASSERT_EQ(2, static_cast<int>(builder_->num_fields()));
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
ASSERT_OK(list_vb->AppendNull());
ASSERT_OK(list_vb->AppendNull());
ASSERT_EQ(2, list_vb->length());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_OK(int_vb->AppendNull());
ASSERT_OK(int_vb->AppendNull());
ASSERT_EQ(2, int_vb->length());
@@ -2987,9 +2988,9 @@ TEST_F(TestStructBuilder, TestBasics) {
vector<uint8_t> list_is_valid = {1, 0, 1, 1};
vector<uint8_t> struct_is_valid = {1, 1, 1, 1};
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
- Int8Builder* char_vb = static_cast<Int8Builder*>(list_vb->value_builder());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
+ Int8Builder* char_vb = checked_cast<Int8Builder*>(list_vb->value_builder());
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_EQ(2, static_cast<int>(builder_->num_fields()));
EXPECT_OK(builder_->Resize(list_lengths.size()));
@@ -3023,9 +3024,9 @@ TEST_F(TestStructBuilder, BulkAppend) {
vector<uint8_t> list_is_valid = {1, 0, 1, 1};
vector<uint8_t> struct_is_valid = {1, 1, 1, 1};
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
- Int8Builder* char_vb = static_cast<Int8Builder*>(list_vb->value_builder());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
+ Int8Builder* char_vb = checked_cast<Int8Builder*>(list_vb->value_builder());
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_OK(builder_->Resize(list_lengths.size()));
ASSERT_OK(char_vb->Resize(list_values.size()));
@@ -3055,9 +3056,9 @@ TEST_F(TestStructBuilder, BulkAppendInvalid) {
vector<uint8_t> list_is_valid = {1, 0, 1, 1};
vector<uint8_t> struct_is_valid = {1, 0, 1, 1}; // should be 1, 1, 1, 1
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
- Int8Builder* char_vb = static_cast<Int8Builder*>(list_vb->value_builder());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
+ Int8Builder* char_vb = checked_cast<Int8Builder*>(list_vb->value_builder());
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_OK(builder_->Reserve(list_lengths.size()));
ASSERT_OK(char_vb->Reserve(list_values.size()));
@@ -3097,9 +3098,9 @@ TEST_F(TestStructBuilder, TestEquality) {
vector<uint8_t> unequal_list_is_valid = {1, 1, 1, 1};
vector<uint8_t> unequal_struct_is_valid = {1, 0, 0, 1};
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
- Int8Builder* char_vb = static_cast<Int8Builder*>(list_vb->value_builder());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
+ Int8Builder* char_vb = checked_cast<Int8Builder*>(list_vb->value_builder());
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_OK(builder_->Reserve(list_lengths.size()));
ASSERT_OK(char_vb->Reserve(list_values.size()));
ASSERT_OK(int_vb->Reserve(int_values.size()));
@@ -3226,9 +3227,9 @@ TEST_F(TestStructBuilder, TestSlice) {
vector<uint8_t> list_is_valid = {1, 0, 1, 1};
vector<uint8_t> struct_is_valid = {1, 1, 1, 1};
- ListBuilder* list_vb = static_cast<ListBuilder*>(builder_->field_builder(0));
- Int8Builder* char_vb = static_cast<Int8Builder*>(list_vb->value_builder());
- Int32Builder* int_vb = static_cast<Int32Builder*>(builder_->field_builder(1));
+ ListBuilder* list_vb = checked_cast<ListBuilder*>(builder_->field_builder(0));
+ Int8Builder* char_vb = checked_cast<Int8Builder*>(list_vb->value_builder());
+ Int32Builder* int_vb = checked_cast<Int32Builder*>(builder_->field_builder(1));
ASSERT_OK(builder_->Reserve(list_lengths.size()));
ASSERT_OK(char_vb->Reserve(list_values.size()));
ASSERT_OK(int_vb->Reserve(int_values.size()));
diff --git a/cpp/src/arrow/array.cc b/cpp/src/arrow/array.cc
index e854114..fb6ccaf 100644
--- a/cpp/src/arrow/array.cc
+++ b/cpp/src/arrow/array.cc
@@ -31,6 +31,7 @@
#include "arrow/status.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
@@ -208,7 +209,7 @@ Status ListArray::FromArrays(const Array& offsets, const Array& values, MemoryPo
BufferVector buffers = {};
- const auto& typed_offsets = static_cast<const Int32Array&>(offsets);
+ const auto& typed_offsets = checked_cast<const Int32Array&>(offsets);
const int64_t num_offsets = offsets.length();
@@ -265,7 +266,7 @@ void ListArray::SetData(const std::shared_ptr<ArrayData>& data) {
}
std::shared_ptr<DataType> ListArray::value_type() const {
- return static_cast<const ListType&>(*type()).value_type();
+ return checked_cast<const ListType&>(*type()).value_type();
}
std::shared_ptr<Array> ListArray::values() const { return values_; }
@@ -329,7 +330,7 @@ FixedSizeBinaryArray::FixedSizeBinaryArray(const std::shared_ptr<DataType>& type
const std::shared_ptr<Buffer>& null_bitmap,
int64_t null_count, int64_t offset)
: PrimitiveArray(type, length, data, null_bitmap, null_count, offset),
- byte_width_(static_cast<const FixedSizeBinaryType&>(*type).byte_width()) {}
+ byte_width_(checked_cast<const FixedSizeBinaryType&>(*type).byte_width()) {}
const uint8_t* FixedSizeBinaryArray::GetValue(int64_t i) const {
return raw_values_ + (i + data_->offset) * byte_width_;
@@ -344,7 +345,7 @@ Decimal128Array::Decimal128Array(const std::shared_ptr<ArrayData>& data)
}
std::string Decimal128Array::FormatValue(int64_t i) const {
- const auto& type_ = static_cast<const Decimal128Type&>(*type());
+ const auto& type_ = checked_cast<const Decimal128Type&>(*type());
const Decimal128 value(GetValue(i));
return value.ToString(type_.scale());
}
@@ -487,8 +488,8 @@ Status UnionArray::MakeDense(const Array& type_ids, const Array& value_offsets,
}
BufferVector buffers = {type_ids.null_bitmap(),
- static_cast<const UInt8Array&>(type_ids).values(),
- static_cast<const Int32Array&>(value_offsets).values()};
+ checked_cast<const Int8Array&>(type_ids).values(),
+ checked_cast<const Int32Array&>(value_offsets).values()};
auto union_type = union_(children, UnionMode::DENSE);
auto internal_data = ArrayData::Make(union_type, type_ids.length(), std::move(buffers),
type_ids.null_count(), type_ids.offset());
@@ -506,7 +507,7 @@ Status UnionArray::MakeSparse(const Array& type_ids,
return Status::Invalid("UnionArray type_ids must be signed int8");
}
BufferVector buffers = {type_ids.null_bitmap(),
- static_cast<const UInt8Array&>(type_ids).values(), nullptr};
+ checked_cast<const Int8Array&>(type_ids).values(), nullptr};
auto union_type = union_(children, UnionMode::SPARSE);
auto internal_data = ArrayData::Make(union_type, type_ids.length(), std::move(buffers),
type_ids.null_count(), type_ids.offset());
@@ -559,7 +560,7 @@ template <typename ArrowType>
Status ValidateDictionaryIndices(const std::shared_ptr<Array>& indices,
const int64_t upper_bound) {
using ArrayType = typename TypeTraits<ArrowType>::ArrayType;
- const auto& array = static_cast<const ArrayType&>(*indices);
+ const auto& array = checked_cast<const ArrayType&>(*indices);
const typename ArrowType::c_type* data = array.raw_values();
const int64_t size = array.length();
@@ -583,14 +584,14 @@ Status ValidateDictionaryIndices(const std::shared_ptr<Array>& indices,
}
DictionaryArray::DictionaryArray(const std::shared_ptr<ArrayData>& data)
- : dict_type_(static_cast<const DictionaryType*>(data->type.get())) {
+ : dict_type_(checked_cast<const DictionaryType*>(data->type.get())) {
DCHECK_EQ(data->type->id(), Type::DICTIONARY);
SetData(data);
}
DictionaryArray::DictionaryArray(const std::shared_ptr<DataType>& type,
const std::shared_ptr<Array>& indices)
- : dict_type_(static_cast<const DictionaryType*>(type.get())) {
+ : dict_type_(checked_cast<const DictionaryType*>(type.get())) {
DCHECK_EQ(type->id(), Type::DICTIONARY);
DCHECK_EQ(indices->type_id(), dict_type_->index_type()->id());
auto data = indices->data()->Copy();
@@ -602,7 +603,7 @@ Status DictionaryArray::FromArrays(const std::shared_ptr<DataType>& type,
const std::shared_ptr<Array>& indices,
std::shared_ptr<Array>* out) {
DCHECK_EQ(type->id(), Type::DICTIONARY);
- const auto& dict = static_cast<const DictionaryType&>(*type);
+ const auto& dict = checked_cast<const DictionaryType&>(*type);
DCHECK_EQ(indices->type_id(), dict.index_type()->id());
int64_t upper_bound = dict.dictionary()->length();
diff --git a/cpp/src/arrow/array.h b/cpp/src/arrow/array.h
index 1b152c4..6f61511 100644
--- a/cpp/src/arrow/array.h
+++ b/cpp/src/arrow/array.h
@@ -30,6 +30,7 @@
#include "arrow/type_fwd.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/macros.h"
#include "arrow/util/visibility.h"
#include "arrow/visitor.h"
@@ -583,7 +584,7 @@ class ARROW_EXPORT FixedSizeBinaryArray : public PrimitiveArray {
protected:
inline void SetData(const std::shared_ptr<ArrayData>& data) {
this->PrimitiveArray::SetData(data);
- byte_width_ = static_cast<const FixedSizeBinaryType&>(*type()).byte_width();
+ byte_width_ = checked_cast<const FixedSizeBinaryType&>(*type()).byte_width();
}
int32_t byte_width_;
@@ -693,7 +694,7 @@ class ARROW_EXPORT UnionArray : public Array {
const type_id_t* raw_type_ids() const { return raw_type_ids_ + data_->offset; }
const int32_t* raw_value_offsets() const { return raw_value_offsets_ + data_->offset; }
- UnionMode::type mode() const { return static_cast<const UnionType&>(*type()).mode(); }
+ UnionMode::type mode() const { return checked_cast<const UnionType&>(*type()).mode(); }
// Return the given field as an individual array.
// For sparse unions, the returned array has its offset, length and null
diff --git a/cpp/src/arrow/builder.cc b/cpp/src/arrow/builder.cc
index 71af87a..39363fd 100644
--- a/cpp/src/arrow/builder.cc
+++ b/cpp/src/arrow/builder.cc
@@ -32,6 +32,7 @@
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/cpu-info.h"
#include "arrow/util/decimal.h"
#include "arrow/util/hash-util.h"
@@ -905,7 +906,7 @@ DictionaryBuilder<FixedSizeBinaryType>::DictionaryBuilder(
dict_builder_(type, pool),
overflow_dict_builder_(type, pool),
values_builder_(pool),
- byte_width_(static_cast<const FixedSizeBinaryType&>(*type).byte_width()) {
+ byte_width_(checked_cast<const FixedSizeBinaryType&>(*type).byte_width()) {
if (!::arrow::CpuInfo::initialized()) {
::arrow::CpuInfo::Init();
}
@@ -993,7 +994,7 @@ Status DictionaryBuilder<T>::Append(const Scalar& value) {
template <typename T>
Status DictionaryBuilder<T>::AppendArray(const Array& array) {
- const auto& numeric_array = static_cast<const NumericArray<T>&>(array);
+ const auto& numeric_array = checked_cast<const NumericArray<T>&>(array);
for (int64_t i = 0; i < array.length(); i++) {
if (array.IsNull(i)) {
RETURN_NOT_OK(AppendNull());
@@ -1017,7 +1018,7 @@ Status DictionaryBuilder<FixedSizeBinaryType>::AppendArray(const Array& array) {
return Status::Invalid("Cannot append FixedSizeBinary array with non-matching type");
}
- const auto& numeric_array = static_cast<const FixedSizeBinaryArray&>(array);
+ const auto& numeric_array = checked_cast<const FixedSizeBinaryArray&>(array);
for (int64_t i = 0; i < array.length(); i++) {
if (array.IsNull(i)) {
RETURN_NOT_OK(AppendNull());
@@ -1133,7 +1134,7 @@ bool DictionaryBuilder<T>::SlotDifferent(hash_slot_t index, const Scalar& value)
template <>
bool DictionaryBuilder<FixedSizeBinaryType>::SlotDifferent(hash_slot_t index,
const Scalar& value) {
- int32_t width = static_cast<const FixedSizeBinaryType&>(*type_).byte_width();
+ int32_t width = checked_cast<const FixedSizeBinaryType&>(*type_).byte_width();
bool value_found = false;
if (index >= entry_id_offset_) {
const Scalar other =
@@ -1172,7 +1173,7 @@ Status DictionaryBuilder<T>::AppendDictionary(const Scalar& value) {
\
template <> \
Status DictionaryBuilder<Type>::AppendArray(const Array& array) { \
- const BinaryArray& binary_array = static_cast<const BinaryArray&>(array); \
+ const BinaryArray& binary_array = checked_cast<const BinaryArray&>(array); \
WrappedBinary value(nullptr, 0); \
for (int64_t i = 0; i < array.length(); i++) { \
if (array.IsNull(i)) { \
@@ -1553,7 +1554,7 @@ Status StringBuilder::Append(const char** values, int64_t length,
FixedSizeBinaryBuilder::FixedSizeBinaryBuilder(const std::shared_ptr<DataType>& type,
MemoryPool* pool)
: ArrayBuilder(type, pool),
- byte_width_(static_cast<const FixedSizeBinaryType&>(*type).byte_width()),
+ byte_width_(checked_cast<const FixedSizeBinaryType&>(*type).byte_width()),
byte_builder_(pool) {}
Status FixedSizeBinaryBuilder::AppendValues(const uint8_t* data, int64_t length,
@@ -1669,7 +1670,7 @@ Status MakeBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
case Type::LIST: {
std::unique_ptr<ArrayBuilder> value_builder;
std::shared_ptr<DataType> value_type =
- static_cast<ListType*>(type.get())->value_type();
+ checked_cast<const ListType&>(*type).value_type();
RETURN_NOT_OK(MakeBuilder(pool, value_type, &value_builder));
out->reset(new ListBuilder(pool, std::move(value_builder)));
return Status::OK();
diff --git a/cpp/src/arrow/compare.cc b/cpp/src/arrow/compare.cc
index b7b9313..51d8aee 100644
--- a/cpp/src/arrow/compare.cc
+++ b/cpp/src/arrow/compare.cc
@@ -29,6 +29,7 @@
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include "arrow/visitor_inline.h"
@@ -51,7 +52,7 @@ class RangeEqualsVisitor {
template <typename ArrayType>
inline Status CompareValues(const ArrayType& left) {
- const auto& right = static_cast<const ArrayType&>(right_);
+ const auto& right = checked_cast<const ArrayType&>(right_);
for (int64_t i = left_start_idx_, o_i = right_start_idx_; i < left_end_idx_;
++i, ++o_i) {
@@ -67,7 +68,7 @@ class RangeEqualsVisitor {
}
bool CompareBinaryRange(const BinaryArray& left) const {
- const auto& right = static_cast<const BinaryArray&>(right_);
+ const auto& right = checked_cast<const BinaryArray&>(right_);
for (int64_t i = left_start_idx_, o_i = right_start_idx_; i < left_end_idx_;
++i, ++o_i) {
@@ -96,7 +97,7 @@ class RangeEqualsVisitor {
}
bool CompareLists(const ListArray& left) {
- const auto& right = static_cast<const ListArray&>(right_);
+ const auto& right = checked_cast<const ListArray&>(right_);
const std::shared_ptr<Array>& left_values = left.values();
const std::shared_ptr<Array>& right_values = right.values();
@@ -125,7 +126,7 @@ class RangeEqualsVisitor {
}
bool CompareStructs(const StructArray& left) {
- const auto& right = static_cast<const StructArray&>(right_);
+ const auto& right = checked_cast<const StructArray&>(right_);
bool equal_fields = true;
for (int64_t i = left_start_idx_, o_i = right_start_idx_; i < left_end_idx_;
++i, ++o_i) {
@@ -146,14 +147,14 @@ class RangeEqualsVisitor {
}
bool CompareUnions(const UnionArray& left) const {
- const auto& right = static_cast<const UnionArray&>(right_);
+ const auto& right = checked_cast<const UnionArray&>(right_);
const UnionMode::type union_mode = left.mode();
if (union_mode != right.mode()) {
return false;
}
- const auto& left_type = static_cast<const UnionType&>(*left.type());
+ const auto& left_type = checked_cast<const UnionType&>(*left.type());
// Define a mapping from the type id to child number
uint8_t max_code = 0;
@@ -213,7 +214,7 @@ class RangeEqualsVisitor {
}
Status Visit(const FixedSizeBinaryArray& left) {
- const auto& right = static_cast<const FixedSizeBinaryArray&>(right_);
+ const auto& right = checked_cast<const FixedSizeBinaryArray&>(right_);
int32_t width = left.byte_width();
@@ -247,7 +248,7 @@ class RangeEqualsVisitor {
}
Status Visit(const Decimal128Array& left) {
- return Visit(static_cast<const FixedSizeBinaryArray&>(left));
+ return Visit(checked_cast<const FixedSizeBinaryArray&>(left));
}
Status Visit(const NullArray& left) {
@@ -278,7 +279,7 @@ class RangeEqualsVisitor {
}
Status Visit(const DictionaryArray& left) {
- const auto& right = static_cast<const DictionaryArray&>(right_);
+ const auto& right = checked_cast<const DictionaryArray&>(right_);
if (!left.dictionary()->Equals(right.dictionary())) {
result_ = false;
return Status::OK();
@@ -343,7 +344,7 @@ class ArrayEqualsVisitor : public RangeEqualsVisitor {
}
Status Visit(const BooleanArray& left) {
- const auto& right = static_cast<const BooleanArray&>(right_);
+ const auto& right = checked_cast<const BooleanArray&>(right_);
if (left.null_count() > 0) {
const uint8_t* left_data = left.values()->data();
@@ -369,13 +370,13 @@ class ArrayEqualsVisitor : public RangeEqualsVisitor {
!std::is_base_of<BooleanArray, T>::value,
Status>::type
Visit(const T& left) {
- result_ = IsEqualPrimitive(left, static_cast<const PrimitiveArray&>(right_));
+ result_ = IsEqualPrimitive(left, checked_cast<const PrimitiveArray&>(right_));
return Status::OK();
}
template <typename ArrayType>
bool ValueOffsetsEqual(const ArrayType& left) {
- const auto& right = static_cast<const ArrayType&>(right_);
+ const auto& right = checked_cast<const ArrayType&>(right_);
if (left.offset() == 0 && right.offset() == 0) {
return left.value_offsets()->Equals(*right.value_offsets(),
@@ -399,7 +400,7 @@ class ArrayEqualsVisitor : public RangeEqualsVisitor {
}
bool CompareBinary(const BinaryArray& left) {
- const auto& right = static_cast<const BinaryArray&>(right_);
+ const auto& right = checked_cast<const BinaryArray&>(right_);
bool equal_offsets = ValueOffsetsEqual<BinaryArray>(left);
if (!equal_offsets) {
@@ -451,7 +452,7 @@ class ArrayEqualsVisitor : public RangeEqualsVisitor {
}
Status Visit(const ListArray& left) {
- const auto& right = static_cast<const ListArray&>(right_);
+ const auto& right = checked_cast<const ListArray&>(right_);
bool equal_offsets = ValueOffsetsEqual<ListArray>(left);
if (!equal_offsets) {
result_ = false;
@@ -465,7 +466,7 @@ class ArrayEqualsVisitor : public RangeEqualsVisitor {
}
Status Visit(const DictionaryArray& left) {
- const auto& right = static_cast<const DictionaryArray&>(right_);
+ const auto& right = checked_cast<const DictionaryArray&>(right_);
if (!left.dictionary()->Equals(right.dictionary())) {
result_ = false;
} else {
@@ -516,13 +517,13 @@ class ApproxEqualsVisitor : public ArrayEqualsVisitor {
Status Visit(const FloatArray& left) {
result_ =
- FloatingApproxEquals<FloatType>(left, static_cast<const FloatArray&>(right_));
+ FloatingApproxEquals<FloatType>(left, checked_cast<const FloatArray&>(right_));
return Status::OK();
}
Status Visit(const DoubleArray& left) {
result_ =
- FloatingApproxEquals<DoubleType>(left, static_cast<const DoubleArray&>(right_));
+ FloatingApproxEquals<DoubleType>(left, checked_cast<const DoubleArray&>(right_));
return Status::OK();
}
};
@@ -596,25 +597,25 @@ class TypeEqualsVisitor {
std::is_base_of<DateType, T>::value,
Status>::type
Visit(const T& left) {
- const auto& right = static_cast<const T&>(right_);
+ const auto& right = checked_cast<const T&>(right_);
result_ = left.unit() == right.unit();
return Status::OK();
}
Status Visit(const TimestampType& left) {
- const auto& right = static_cast<const TimestampType&>(right_);
+ const auto& right = checked_cast<const TimestampType&>(right_);
result_ = left.unit() == right.unit() && left.timezone() == right.timezone();
return Status::OK();
}
Status Visit(const FixedSizeBinaryType& left) {
- const auto& right = static_cast<const FixedSizeBinaryType&>(right_);
+ const auto& right = checked_cast<const FixedSizeBinaryType&>(right_);
result_ = left.byte_width() == right.byte_width();
return Status::OK();
}
Status Visit(const Decimal128Type& left) {
- const auto& right = static_cast<const Decimal128Type&>(right_);
+ const auto& right = checked_cast<const Decimal128Type&>(right_);
result_ = left.precision() == right.precision() && left.scale() == right.scale();
return Status::OK();
}
@@ -624,7 +625,7 @@ class TypeEqualsVisitor {
Status Visit(const StructType& left) { return VisitChildren(left); }
Status Visit(const UnionType& left) {
- const auto& right = static_cast<const UnionType&>(right_);
+ const auto& right = checked_cast<const UnionType&>(right_);
if (left.mode() != right.mode() ||
left.type_codes().size() != right.type_codes().size()) {
@@ -654,7 +655,7 @@ class TypeEqualsVisitor {
}
Status Visit(const DictionaryType& left) {
- const auto& right = static_cast<const DictionaryType&>(right_);
+ const auto& right = checked_cast<const DictionaryType&>(right_);
result_ = left.index_type()->Equals(right.index_type()) &&
left.dictionary()->Equals(right.dictionary()) &&
(left.ordered() == right.ordered());
@@ -737,7 +738,7 @@ bool TensorEquals(const Tensor& left, const Tensor& right) {
if (shape != right.shape()) {
are_equal = false;
} else {
- const auto& type = static_cast<const FixedWidthType&>(*left.type());
+ const auto& type = checked_cast<const FixedWidthType&>(*left.type());
are_equal =
StridedTensorContentEquals(0, 0, 0, type.bit_width() / 8, left, right);
}
diff --git a/cpp/src/arrow/compute/kernels/cast.cc b/cpp/src/arrow/compute/kernels/cast.cc
index 185a966..e5b9eaf 100644
--- a/cpp/src/arrow/compute/kernels/cast.cc
+++ b/cpp/src/arrow/compute/kernels/cast.cc
@@ -35,6 +35,7 @@
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
@@ -348,8 +349,8 @@ struct CastFunctor<TimestampType, TimestampType> {
void operator()(FunctionContext* ctx, const CastOptions& options,
const ArrayData& input, ArrayData* output) {
// If units are the same, zero copy, otherwise convert
- const auto& in_type = static_cast<const TimestampType&>(*input.type);
- const auto& out_type = static_cast<const TimestampType&>(*output->type);
+ const auto& in_type = checked_cast<const TimestampType&>(*input.type);
+ const auto& out_type = checked_cast<const TimestampType&>(*output->type);
if (in_type.unit() == out_type.unit()) {
CopyData(input, output);
@@ -369,7 +370,7 @@ template <>
struct CastFunctor<Date32Type, TimestampType> {
void operator()(FunctionContext* ctx, const CastOptions& options,
const ArrayData& input, ArrayData* output) {
- const auto& in_type = static_cast<const TimestampType&>(*input.type);
+ const auto& in_type = checked_cast<const TimestampType&>(*input.type);
static const int64_t kTimestampToDateFactors[4] = {
86400LL, // SECOND
@@ -387,7 +388,7 @@ template <>
struct CastFunctor<Date64Type, TimestampType> {
void operator()(FunctionContext* ctx, const CastOptions& options,
const ArrayData& input, ArrayData* output) {
- const auto& in_type = static_cast<const TimestampType&>(*input.type);
+ const auto& in_type = checked_cast<const TimestampType&>(*input.type);
std::pair<bool, int64_t> conversion =
kTimeConversionTable[static_cast<int>(in_type.unit())]
@@ -441,8 +442,8 @@ struct CastFunctor<O, I,
using out_t = typename O::c_type;
// If units are the same, zero copy, otherwise convert
- const auto& in_type = static_cast<const I&>(*input.type);
- const auto& out_type = static_cast<const O&>(*output->type);
+ const auto& in_type = checked_cast<const I&>(*input.type);
+ const auto& out_type = checked_cast<const O&>(*output->type);
if (in_type.unit() == out_type.unit()) {
CopyData(input, output);
@@ -531,7 +532,7 @@ void UnpackFixedSizeBinaryDictionary(FunctionContext* ctx, const Array& indices,
const index_c_type* in = GetValues<index_c_type>(*indices.data(), 1);
int32_t byte_width =
- static_cast<const FixedSizeBinaryType&>(*output->type).byte_width();
+ checked_cast<const FixedSizeBinaryType&>(*output->type).byte_width();
uint8_t* out = output->buffers[1]->mutable_data() + byte_width * output->offset;
@@ -562,10 +563,10 @@ struct CastFunctor<
const ArrayData& input, ArrayData* output) {
DictionaryArray dict_array(input.Copy());
- const DictionaryType& type = static_cast<const DictionaryType&>(*input.type);
+ const DictionaryType& type = checked_cast<const DictionaryType&>(*input.type);
const DataType& values_type = *type.dictionary()->type();
const FixedSizeBinaryArray& dictionary =
- static_cast<const FixedSizeBinaryArray&>(*type.dictionary());
+ checked_cast<const FixedSizeBinaryArray&>(*type.dictionary());
// Check if values and output type match
DCHECK(values_type.Equals(*output->type))
@@ -600,7 +601,7 @@ Status UnpackBinaryDictionary(FunctionContext* ctx, const Array& indices,
using index_c_type = typename IndexType::c_type;
std::unique_ptr<ArrayBuilder> builder;
RETURN_NOT_OK(MakeBuilder(ctx->memory_pool(), output->type, &builder));
- BinaryBuilder* binary_builder = static_cast<BinaryBuilder*>(builder.get());
+ BinaryBuilder* binary_builder = checked_cast<BinaryBuilder*>(builder.get());
const index_c_type* in = GetValues<index_c_type>(*indices.data(), 1);
if (indices.null_count() != 0) {
@@ -642,9 +643,9 @@ struct CastFunctor<T, DictionaryType,
const ArrayData& input, ArrayData* output) {
DictionaryArray dict_array(input.Copy());
- const DictionaryType& type = static_cast<const DictionaryType&>(*input.type);
+ const DictionaryType& type = checked_cast<const DictionaryType&>(*input.type);
const DataType& values_type = *type.dictionary()->type();
- const BinaryArray& dictionary = static_cast<const BinaryArray&>(*type.dictionary());
+ const BinaryArray& dictionary = checked_cast<const BinaryArray&>(*type.dictionary());
// Check if values and output type match
DCHECK(values_type.Equals(*output->type))
@@ -702,7 +703,7 @@ struct CastFunctor<T, DictionaryType,
DictionaryArray dict_array(input.Copy());
- const DictionaryType& type = static_cast<const DictionaryType&>(*input.type);
+ const DictionaryType& type = checked_cast<const DictionaryType&>(*input.type);
const DataType& values_type = *type.dictionary()->type();
// Check if values and output type match
@@ -780,7 +781,7 @@ static Status AllocateIfNotPreallocated(FunctionContext* ctx, const ArrayData& i
}
if (type_id != Type::NA) {
- const auto& fw_type = static_cast<const FixedWidthType&>(*out->type);
+ const auto& fw_type = checked_cast<const FixedWidthType&>(*out->type);
int bit_width = fw_type.bit_width();
int64_t buffer_size = 0;
@@ -985,9 +986,9 @@ Status GetListCastFunc(const DataType& in_type, const std::shared_ptr<DataType>&
// Kernel will be null
return Status::OK();
}
- const DataType& in_value_type = *static_cast<const ListType&>(in_type).value_type();
+ const DataType& in_value_type = *checked_cast<const ListType&>(in_type).value_type();
std::shared_ptr<DataType> out_value_type =
- static_cast<const ListType&>(*out_type).value_type();
+ checked_cast<const ListType&>(*out_type).value_type();
std::unique_ptr<UnaryKernel> child_caster;
RETURN_NOT_OK(GetCastFunction(in_value_type, out_value_type, options, &child_caster));
*kernel =
diff --git a/cpp/src/arrow/compute/kernels/hash.cc b/cpp/src/arrow/compute/kernels/hash.cc
index dbce6e5..1c849d0 100644
--- a/cpp/src/arrow/compute/kernels/hash.cc
+++ b/cpp/src/arrow/compute/kernels/hash.cc
@@ -30,6 +30,7 @@
#include "arrow/compute/context.h"
#include "arrow/compute/kernel.h"
#include "arrow/compute/kernels/util-internal.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/hash-util.h"
#include "arrow/util/hash.h"
@@ -152,7 +153,7 @@ class HashTableKernel<Type, Action, enable_if_null<Type>> : public HashTable {
if (!initialized_) {
RETURN_NOT_OK(Init());
}
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
for (int64_t i = 0; i < arr.length; ++i) {
action->ObserveNull();
@@ -242,7 +243,7 @@ class HashTableKernel<
}
const T* values = GetValues<T>(arr, 1);
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
@@ -326,7 +327,7 @@ class HashTableKernel<Type, Action, enable_if_boolean<Type>> : public HashTable
}
Status Append(const ArrayData& arr) override {
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
@@ -423,7 +424,7 @@ class HashTableKernel<Type, Action, enable_if_binary<Type>> : public HashTable {
data = GetValues<uint8_t>(arr, 2);
}
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
#define HASH_INNER_LOOP() \
@@ -521,7 +522,7 @@ class HashTableKernel<Type, Action, enable_if_fixed_size_binary<Type>>
public:
HashTableKernel(const std::shared_ptr<DataType>& type, MemoryPool* pool)
: HashTable(type, pool), dict_data_(pool), dict_size_(0) {
- const auto& fw_type = static_cast<const FixedSizeBinaryType&>(*type);
+ const auto& fw_type = checked_cast<const FixedSizeBinaryType&>(*type);
byte_width_ = fw_type.bit_width() / 8;
}
@@ -537,7 +538,7 @@ class HashTableKernel<Type, Action, enable_if_fixed_size_binary<Type>>
const uint8_t* data = GetValues<uint8_t>(arr, 1);
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
#define HASH_INNER_LOOP() \
@@ -644,7 +645,7 @@ class HashTableKernel<Type, Action, enable_if_8bit_int<Type>> : public HashTable
Status Append(const ArrayData& arr) override {
const T* values = GetValues<T>(arr, 1);
- auto action = static_cast<Action*>(this);
+ auto action = checked_cast<Action*>(this);
RETURN_NOT_OK(action->Reserve(arr.length));
#define HASH_INNER_LOOP() \
diff --git a/cpp/src/arrow/io/io-memory-test.cc b/cpp/src/arrow/io/io-memory-test.cc
index 8c2e8c3..0652fe7 100644
--- a/cpp/src/arrow/io/io-memory-test.cc
+++ b/cpp/src/arrow/io/io-memory-test.cc
@@ -29,6 +29,7 @@
#include "arrow/memory_pool.h"
#include "arrow/status.h"
#include "arrow/test-util.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
namespace io {
@@ -73,7 +74,7 @@ TEST_F(TestBufferOutputStream, WriteAfterFinish) {
std::string data = "data123456";
ASSERT_OK(stream_->Write(data));
- auto buffer_stream = static_cast<BufferOutputStream*>(stream_.get());
+ auto buffer_stream = checked_cast<BufferOutputStream*>(stream_.get());
std::shared_ptr<Buffer> buffer;
ASSERT_OK(buffer_stream->Finish(&buffer));
diff --git a/cpp/src/arrow/ipc/feather-test.cc b/cpp/src/arrow/ipc/feather-test.cc
index ae1489a..cea5176 100644
--- a/cpp/src/arrow/ipc/feather-test.cc
+++ b/cpp/src/arrow/ipc/feather-test.cc
@@ -31,6 +31,7 @@
#include "arrow/pretty_print.h"
#include "arrow/table.h"
#include "arrow/test-util.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
namespace ipc {
@@ -365,7 +366,7 @@ TEST_F(TestTableWriter, TimeTypes) {
std::shared_ptr<Array> date_array;
ArrayFromVector<Date32Type, int32_t>(is_valid, date_values_vec, &date_array);
- const auto& prim_values = static_cast<const PrimitiveArray&>(*values);
+ const auto& prim_values = checked_cast<const PrimitiveArray&>(*values);
BufferVector buffers = {prim_values.null_bitmap(), prim_values.values()};
std::vector<std::shared_ptr<ArrayData>> arrays;
diff --git a/cpp/src/arrow/ipc/feather.cc b/cpp/src/arrow/ipc/feather.cc
index 7e762ac..1cd3007 100644
--- a/cpp/src/arrow/ipc/feather.cc
+++ b/cpp/src/arrow/ipc/feather.cc
@@ -38,6 +38,7 @@
#include "arrow/table.h"
#include "arrow/type.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include "arrow/visitor.h"
@@ -611,7 +612,7 @@ class TableWriter::TableWriterImpl : public ArrayVisitor {
const uint8_t* values_buffer = nullptr;
if (is_binary_like(values.type_id())) {
- const auto& bin_values = static_cast<const BinaryArray&>(values);
+ const auto& bin_values = checked_cast<const BinaryArray&>(values);
int64_t offset_bytes = sizeof(int32_t) * (values.length() + 1);
@@ -632,8 +633,8 @@ class TableWriter::TableWriterImpl : public ArrayVisitor {
values_buffer = bin_values.value_data()->data();
}
} else {
- const auto& prim_values = static_cast<const PrimitiveArray&>(values);
- const auto& fw_type = static_cast<const FixedWidthType&>(*values.type());
+ const auto& prim_values = checked_cast<const PrimitiveArray&>(values);
+ const auto& fw_type = checked_cast<const FixedWidthType&>(*values.type());
values_bytes = BitUtil::BytesForBits(values.length() * fw_type.bit_width());
@@ -688,7 +689,7 @@ class TableWriter::TableWriterImpl : public ArrayVisitor {
#undef VISIT_PRIMITIVE
Status Visit(const DictionaryArray& values) override {
- const auto& dict_type = static_cast<const DictionaryType&>(*values.type());
+ const auto& dict_type = checked_cast<const DictionaryType&>(*values.type());
if (!is_integer(values.indices()->type_id())) {
return Status::Invalid("Category values must be integers");
@@ -707,7 +708,7 @@ class TableWriter::TableWriterImpl : public ArrayVisitor {
Status Visit(const TimestampArray& values) override {
RETURN_NOT_OK(WritePrimitiveValues(values));
- const auto& ts_type = static_cast<const TimestampType&>(*values.type());
+ const auto& ts_type = checked_cast<const TimestampType&>(*values.type());
current_column_->SetTimestamp(ts_type.unit(), ts_type.timezone());
return Status::OK();
}
@@ -720,7 +721,7 @@ class TableWriter::TableWriterImpl : public ArrayVisitor {
Status Visit(const Time32Array& values) override {
RETURN_NOT_OK(WritePrimitiveValues(values));
- auto unit = static_cast<const Time32Type&>(*values.type()).unit();
+ auto unit = checked_cast<const Time32Type&>(*values.type()).unit();
current_column_->SetTime(unit);
return Status::OK();
}
diff --git a/cpp/src/arrow/ipc/ipc-read-write-test.cc b/cpp/src/arrow/ipc/ipc-read-write-test.cc
index 437585f..bbc279f 100644
--- a/cpp/src/arrow/ipc/ipc-read-write-test.cc
+++ b/cpp/src/arrow/ipc/ipc-read-write-test.cc
@@ -38,6 +38,7 @@
#include "arrow/tensor.h"
#include "arrow/test-util.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
namespace ipc {
@@ -653,14 +654,14 @@ void CheckBatchDictionaries(const RecordBatch& batch) {
// Check that dictionaries that should be the same are the same
auto schema = batch.schema();
- const auto& t0 = static_cast<const DictionaryType&>(*schema->field(0)->type());
- const auto& t1 = static_cast<const DictionaryType&>(*schema->field(1)->type());
+ const auto& t0 = checked_cast<const DictionaryType&>(*schema->field(0)->type());
+ const auto& t1 = checked_cast<const DictionaryType&>(*schema->field(1)->type());
ASSERT_EQ(t0.dictionary().get(), t1.dictionary().get());
// Same dictionary used for list values
- const auto& t3 = static_cast<const ListType&>(*schema->field(3)->type());
- const auto& t3_value = static_cast<const DictionaryType&>(*t3.value_type());
+ const auto& t3 = checked_cast<const ListType&>(*schema->field(3)->type());
+ const auto& t3_value = checked_cast<const DictionaryType&>(*t3.value_type());
ASSERT_EQ(t0.dictionary().get(), t3_value.dictionary().get());
}
diff --git a/cpp/src/arrow/ipc/json-internal.cc b/cpp/src/arrow/ipc/json-internal.cc
index 204bbc4..cb9cf51 100644
--- a/cpp/src/arrow/ipc/json-internal.cc
+++ b/cpp/src/arrow/ipc/json-internal.cc
@@ -33,6 +33,7 @@
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/logging.h"
#include "arrow/util/string.h"
@@ -157,7 +158,7 @@ class SchemaWriter {
writer_->EndObject();
if (type.id() == Type::DICTIONARY) {
- const auto& dict_type = static_cast<const DictionaryType&>(type);
+ const auto& dict_type = checked_cast<const DictionaryType&>(type);
RETURN_NOT_OK(WriteDictionaryMetadata(dict_type));
const DataType& dictionary_type = *dict_type.dictionary()->type();
@@ -516,13 +517,13 @@ class ArrayWriter {
Status Visit(const ListArray& array) {
WriteValidityField(array);
WriteIntegerField("OFFSET", array.raw_value_offsets(), array.length() + 1);
- const auto& type = static_cast<const ListType&>(*array.type());
+ const auto& type = checked_cast<const ListType&>(*array.type());
return WriteChildren(type.children(), {array.values()});
}
Status Visit(const StructArray& array) {
WriteValidityField(array);
- const auto& type = static_cast<const StructType&>(*array.type());
+ const auto& type = checked_cast<const StructType&>(*array.type());
std::vector<std::shared_ptr<Array>> children;
children.reserve(array.num_fields());
for (int i = 0; i < array.num_fields(); ++i) {
@@ -533,7 +534,7 @@ class ArrayWriter {
Status Visit(const UnionArray& array) {
WriteValidityField(array);
- const auto& type = static_cast<const UnionType&>(*array.type());
+ const auto& type = checked_cast<const UnionType&>(*array.type());
WriteIntegerField("TYPE_ID", array.raw_type_ids(), array.length());
if (type.mode() == UnionMode::DENSE) {
@@ -690,7 +691,7 @@ static Status GetTime(const RjObject& json_type, std::shared_ptr<DataType>* type
return Status::Invalid(ss.str());
}
- const auto& fw_type = static_cast<const FixedWidthType&>(**type);
+ const auto& fw_type = checked_cast<const FixedWidthType&>(**type);
int bit_width = it_bit_width->value.GetInt();
if (bit_width != fw_type.bit_width()) {
diff --git a/cpp/src/arrow/ipc/metadata-internal.cc b/cpp/src/arrow/ipc/metadata-internal.cc
index d543239..aaa3cc5 100644
--- a/cpp/src/arrow/ipc/metadata-internal.cc
+++ b/cpp/src/arrow/ipc/metadata-internal.cc
@@ -39,6 +39,7 @@
#include "arrow/tensor.h"
#include "arrow/type.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/key_value_metadata.h"
#include "arrow/util/logging.h"
@@ -189,7 +190,7 @@ static Status UnionToFlatBuffer(FBB& fbb, const DataType& type,
DictionaryMemo* dictionary_memo, Offset* offset) {
RETURN_NOT_OK(AppendChildFields(fbb, type, out_children, dictionary_memo));
- const auto& union_type = static_cast<const UnionType&>(type);
+ const auto& union_type = checked_cast<const UnionType&>(type);
flatbuf::UnionMode mode = union_type.mode() == UnionMode::SPARSE
? flatbuf::UnionMode_Sparse
@@ -348,7 +349,7 @@ static Status TypeToFlatbuffer(FBB& fbb, const DataType& type,
// In this library, the dictionary "type" is a logical construct. Here we
// pass through to the value type, as we've already captured the index
// type in the DictionaryEncoding metadata in the parent field
- value_type = static_cast<const DictionaryType&>(type).dictionary()->type().get();
+ value_type = checked_cast<const DictionaryType&>(type).dictionary()->type().get();
}
switch (value_type->id()) {
@@ -389,7 +390,7 @@ static Status TypeToFlatbuffer(FBB& fbb, const DataType& type,
*offset = FloatToFlatbuffer(fbb, flatbuf::Precision_DOUBLE);
break;
case Type::FIXED_SIZE_BINARY: {
- const auto& fw_type = static_cast<const FixedSizeBinaryType&>(*value_type);
+ const auto& fw_type = checked_cast<const FixedSizeBinaryType&>(*value_type);
*out_type = flatbuf::Type_FixedSizeBinary;
*offset = flatbuf::CreateFixedSizeBinary(fbb, fw_type.byte_width()).Union();
} break;
@@ -410,17 +411,17 @@ static Status TypeToFlatbuffer(FBB& fbb, const DataType& type,
*offset = flatbuf::CreateDate(fbb, flatbuf::DateUnit_MILLISECOND).Union();
break;
case Type::TIME32: {
- const auto& time_type = static_cast<const Time32Type&>(*value_type);
+ const auto& time_type = checked_cast<const Time32Type&>(*value_type);
*out_type = flatbuf::Type_Time;
*offset = flatbuf::CreateTime(fbb, ToFlatbufferUnit(time_type.unit()), 32).Union();
} break;
case Type::TIME64: {
- const auto& time_type = static_cast<const Time64Type&>(*value_type);
+ const auto& time_type = checked_cast<const Time64Type&>(*value_type);
*out_type = flatbuf::Type_Time;
*offset = flatbuf::CreateTime(fbb, ToFlatbufferUnit(time_type.unit()), 64).Union();
} break;
case Type::TIMESTAMP: {
- const auto& ts_type = static_cast<const TimestampType&>(*value_type);
+ const auto& ts_type = checked_cast<const TimestampType&>(*value_type);
*out_type = flatbuf::Type_Timestamp;
flatbuf::TimeUnit fb_unit = ToFlatbufferUnit(ts_type.unit());
@@ -431,7 +432,7 @@ static Status TypeToFlatbuffer(FBB& fbb, const DataType& type,
*offset = flatbuf::CreateTimestamp(fbb, fb_unit, fb_timezone).Union();
} break;
case Type::DECIMAL: {
- const auto& dec_type = static_cast<const Decimal128Type&>(*value_type);
+ const auto& dec_type = checked_cast<const Decimal128Type&>(*value_type);
*out_type = flatbuf::Type_Decimal;
*offset =
flatbuf::CreateDecimal(fbb, dec_type.precision(), dec_type.scale()).Union();
@@ -501,7 +502,7 @@ static DictionaryOffset GetDictionaryEncoding(FBB& fbb, const DictionaryType& ty
// We assume that the dictionary index type (as an integer) has already been
// validated elsewhere, and can safely assume we are dealing with signed
// integers
- const auto& fw_index_type = static_cast<const FixedWidthType&>(*type.index_type());
+ const auto& fw_index_type = checked_cast<const FixedWidthType&>(*type.index_type());
auto index_type_offset = flatbuf::CreateInt(fbb, fw_index_type.bit_width(), true);
@@ -525,7 +526,7 @@ static Status FieldToFlatbuffer(FBB& fbb, const Field& field,
DictionaryOffset dictionary = 0;
if (field.type()->id() == Type::DICTIONARY) {
dictionary = GetDictionaryEncoding(
- fbb, static_cast<const DictionaryType&>(*field.type()), dictionary_memo);
+ fbb, checked_cast<const DictionaryType&>(*field.type()), dictionary_memo);
}
// TODO: produce the list of VectorTypes
diff --git a/cpp/src/arrow/ipc/writer.cc b/cpp/src/arrow/ipc/writer.cc
index cdb3399..84830e6 100644
--- a/cpp/src/arrow/ipc/writer.cc
+++ b/cpp/src/arrow/ipc/writer.cc
@@ -38,6 +38,7 @@
#include "arrow/tensor.h"
#include "arrow/type.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
namespace arrow {
@@ -236,7 +237,7 @@ class RecordBatchSerializer : public ArrayVisitor {
Status VisitFixedWidth(const ArrayType& array) {
std::shared_ptr<Buffer> data = array.values();
- const auto& fw_type = static_cast<const FixedWidthType&>(*array.type());
+ const auto& fw_type = checked_cast<const FixedWidthType&>(*array.type());
const int64_t type_width = fw_type.bit_width() / 8;
int64_t min_length = PaddedLength(array.length() * type_width);
@@ -393,7 +394,7 @@ class RecordBatchSerializer : public ArrayVisitor {
--max_recursion_depth_;
if (array.mode() == UnionMode::DENSE) {
- const auto& type = static_cast<const UnionType&>(*array.type());
+ const auto& type = checked_cast<const UnionType&>(*array.type());
std::shared_ptr<Buffer> value_offsets;
RETURN_NOT_OK(GetTruncatedBuffer<int32_t>(offset, length, array.value_offsets(),
@@ -595,7 +596,7 @@ Status WriteStridedTensorData(int dim_index, int64_t offset, int elem_size,
Status GetContiguousTensor(const Tensor& tensor, MemoryPool* pool,
std::unique_ptr<Tensor>* out) {
- const auto& type = static_cast<const FixedWidthType&>(*tensor.type());
+ const auto& type = checked_cast<const FixedWidthType&>(*tensor.type());
const int elem_size = type.bit_width() / 8;
// TODO(wesm): Do we care enough about this temporary allocation to pass in
@@ -639,7 +640,7 @@ Status WriteTensor(const Tensor& tensor, io::OutputStream* dst, int32_t* metadat
}
} else {
Tensor dummy(tensor.type(), tensor.data(), tensor.shape());
- const auto& type = static_cast<const FixedWidthType&>(*tensor.type());
+ const auto& type = checked_cast<const FixedWidthType&>(*tensor.type());
RETURN_NOT_OK(WriteTensorHeader(dummy, dst, metadata_length, body_length));
// It's important to align the stream position again so that the tensor data
// is aligned.
diff --git a/cpp/src/arrow/pretty_print.cc b/cpp/src/arrow/pretty_print.cc
index 38ccb7b..6663007 100644
--- a/cpp/src/arrow/pretty_print.cc
+++ b/cpp/src/arrow/pretty_print.cc
@@ -27,6 +27,7 @@
#include "arrow/status.h"
#include "arrow/type.h"
#include "arrow/type_traits.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include "arrow/util/string.h"
#include "arrow/visitor_inline.h"
@@ -379,7 +380,7 @@ Status SchemaPrinter::PrintType(const DataType& type) {
indent_ += 2;
WriteIndented("dictionary: ");
- const auto& dict_type = static_cast<const DictionaryType&>(type);
+ const auto& dict_type = checked_cast<const DictionaryType&>(type);
RETURN_NOT_OK(PrettyPrint(*dict_type.dictionary(), indent_, sink_));
indent_ -= 2;
} else {
diff --git a/cpp/src/arrow/python/arrow_to_pandas.cc b/cpp/src/arrow/python/arrow_to_pandas.cc
index 41a07d0..f8887d4 100644
--- a/cpp/src/arrow/python/arrow_to_pandas.cc
+++ b/cpp/src/arrow/python/arrow_to_pandas.cc
@@ -36,6 +36,7 @@
#include "arrow/type_fwd.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
@@ -109,7 +110,7 @@ static inline bool ListTypeSupported(const DataType& type) {
// The above types are all supported.
return true;
case Type::LIST: {
- const ListType& list_type = static_cast<const ListType&>(type);
+ const ListType& list_type = checked_cast<const ListType&>(type);
return ListTypeSupported(*list_type.value_type());
}
default:
@@ -139,9 +140,9 @@ inline void set_numpy_metadata(int type, DataType* datatype, PyArray_Descr* out)
if (type == NPY_DATETIME) {
auto date_dtype = reinterpret_cast<PyArray_DatetimeDTypeMetaData*>(out->c_metadata);
if (datatype->id() == Type::TIMESTAMP) {
- auto timestamp_type = static_cast<TimestampType*>(datatype);
+ const auto& timestamp_type = checked_cast<const TimestampType&>(*datatype);
- switch (timestamp_type->unit()) {
+ switch (timestamp_type.unit()) {
case TimestampType::Unit::SECOND:
date_dtype->meta.base = NPY_FR_s;
break;
@@ -286,7 +287,7 @@ inline const T* GetPrimitiveValues(const Array& arr) {
if (arr.length() == 0) {
return nullptr;
}
- const auto& prim_arr = static_cast<const PrimitiveArray&>(arr);
+ const auto& prim_arr = checked_cast<const PrimitiveArray&>(arr);
const T* raw_values = reinterpret_cast<const T*>(prim_arr.values()->data());
return raw_values + arr.offset();
}
@@ -334,7 +335,7 @@ static Status ConvertBooleanWithNulls(PandasOptions options, const ChunkedArray&
PyObject** out_values) {
PyAcquireGIL lock;
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const BooleanArray&>(*data.chunk(c));
+ const auto& arr = checked_cast<const BooleanArray&>(*data.chunk(c));
for (int64_t i = 0; i < arr.length(); ++i) {
if (arr.IsNull(i)) {
@@ -357,7 +358,7 @@ static Status ConvertBooleanWithNulls(PandasOptions options, const ChunkedArray&
static void ConvertBooleanNoNulls(PandasOptions options, const ChunkedArray& data,
uint8_t* out_values) {
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const BooleanArray&>(*data.chunk(c));
+ const auto& arr = checked_cast<const BooleanArray&>(*data.chunk(c));
for (int64_t i = 0; i < arr.length(); ++i) {
*out_values++ = static_cast<uint8_t>(arr.Value(i));
}
@@ -368,18 +369,18 @@ template <typename T>
static Status ConvertIntegerObjects(PandasOptions options, const ChunkedArray& data,
PyObject** out_values) {
PyAcquireGIL lock;
+ constexpr bool is_signed = std::is_signed<T>::value;
for (int c = 0; c < data.num_chunks(); c++) {
const auto& arr = *data.chunk(c);
- const T* in_values = GetPrimitiveValues<T>(arr);
+ const auto* in_values = GetPrimitiveValues<T>(arr);
for (int i = 0; i < arr.length(); ++i) {
if (arr.IsNull(i)) {
Py_INCREF(Py_None);
*out_values++ = Py_None;
} else {
- *out_values++ = std::is_signed<T>::value
- ? PyLong_FromLongLong(in_values[i])
- : PyLong_FromUnsignedLongLong(in_values[i]);
+ *out_values++ = is_signed ? PyLong_FromLongLong(in_values[i])
+ : PyLong_FromUnsignedLongLong(in_values[i]);
RETURN_IF_PYERROR();
}
}
@@ -393,7 +394,7 @@ inline Status ConvertBinaryLike(PandasOptions options, const ChunkedArray& data,
using ArrayType = typename TypeTraits<Type>::ArrayType;
PyAcquireGIL lock;
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const ArrayType&>(*data.chunk(c));
+ const auto& arr = checked_cast<const ArrayType&>(*data.chunk(c));
const uint8_t* data_ptr;
int32_t length;
@@ -439,7 +440,7 @@ inline Status ConvertFixedSizeBinary(PandasOptions options, const ChunkedArray&
PyObject** out_values) {
PyAcquireGIL lock;
for (int c = 0; c < data.num_chunks(); c++) {
- auto arr = static_cast<FixedSizeBinaryArray*>(data.chunk(c).get());
+ auto arr = checked_cast<FixedSizeBinaryArray*>(data.chunk(c).get());
const uint8_t* data_ptr;
int32_t length =
@@ -473,14 +474,14 @@ inline Status ConvertStruct(PandasOptions options, const ChunkedArray& data,
return Status::OK();
}
// ChunkedArray has at least one chunk
- auto arr = static_cast<const StructArray*>(data.chunk(0).get());
+ auto arr = checked_cast<const StructArray*>(data.chunk(0).get());
// Use it to cache the struct type and number of fields for all chunks
int32_t num_fields = arr->num_fields();
auto array_type = arr->type();
std::vector<OwnedRef> fields_data(num_fields);
OwnedRef dict_item;
for (int c = 0; c < data.num_chunks(); c++) {
- auto arr = static_cast<const StructArray*>(data.chunk(c).get());
+ auto arr = checked_cast<const StructArray*>(data.chunk(c).get());
// Convert the struct arrays first
for (int32_t i = 0; i < num_fields; i++) {
PyObject* numpy_array;
@@ -533,12 +534,12 @@ template <typename ArrowType>
inline Status ConvertListsLike(PandasOptions options, const std::shared_ptr<Column>& col,
PyObject** out_values) {
const ChunkedArray& data = *col->data().get();
- const auto& list_type = static_cast<const ListType&>(*col->type());
+ const auto& list_type = checked_cast<const ListType&>(*col->type());
// Get column of underlying value arrays
std::vector<std::shared_ptr<Array>> value_arrays;
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const ListArray&>(*data.chunk(c));
+ const auto& arr = checked_cast<const ListArray&>(*data.chunk(c));
value_arrays.emplace_back(arr.values());
}
auto flat_column = std::make_shared<Column>(list_type.value_field(), value_arrays);
@@ -642,7 +643,7 @@ static Status ConvertTimes(PandasOptions options, const ChunkedArray& data,
PyDateTime_IMPORT;
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const ArrayType&>(*data.chunk(c));
+ const auto& arr = checked_cast<const ArrayType&>(*data.chunk(c));
auto type = std::dynamic_pointer_cast<TYPE>(arr.type());
DCHECK(type);
@@ -672,7 +673,7 @@ static Status ConvertDecimals(PandasOptions options, const ChunkedArray& data,
PyObject* decimal_constructor = Decimal.obj();
for (int c = 0; c < data.num_chunks(); c++) {
- const auto& arr = static_cast<const arrow::Decimal128Array&>(*data.chunk(c));
+ const auto& arr = checked_cast<const arrow::Decimal128Array&>(*data.chunk(c));
for (int64_t i = 0; i < arr.length(); ++i) {
if (arr.IsNull(i)) {
@@ -978,15 +979,15 @@ class DatetimeBlock : public PandasBlock {
// TODO(wesm): Do we want to make sure to zero out the milliseconds?
ConvertDatetimeNanos<int64_t, 1000000L>(data, out_buffer);
} else if (type == Type::TIMESTAMP) {
- auto ts_type = static_cast<TimestampType*>(col->type().get());
+ const auto& ts_type = checked_cast<const TimestampType&>(*col->type());
- if (ts_type->unit() == TimeUnit::NANO) {
+ if (ts_type.unit() == TimeUnit::NANO) {
ConvertNumericNullable<int64_t>(data, kPandasTimestampNull, out_buffer);
- } else if (ts_type->unit() == TimeUnit::MICRO) {
+ } else if (ts_type.unit() == TimeUnit::MICRO) {
ConvertDatetimeNanos<int64_t, 1000L>(data, out_buffer);
- } else if (ts_type->unit() == TimeUnit::MILLI) {
+ } else if (ts_type.unit() == TimeUnit::MILLI) {
ConvertDatetimeNanos<int64_t, 1000000L>(data, out_buffer);
- } else if (ts_type->unit() == TimeUnit::SECOND) {
+ } else if (ts_type.unit() == TimeUnit::SECOND) {
ConvertDatetimeNanos<int64_t, 1000000000L>(data, out_buffer);
} else {
return Status::NotImplemented("Unsupported time unit");
@@ -1053,7 +1054,7 @@ class CategoricalBlock : public PandasBlock {
// Sniff the first chunk
const std::shared_ptr<Array> arr_first = data.chunk(0);
- const auto& dict_arr_first = static_cast<const DictionaryArray&>(*arr_first);
+ const auto& dict_arr_first = checked_cast<const DictionaryArray&>(*arr_first);
const auto indices_first =
std::static_pointer_cast<ArrayType>(dict_arr_first.indices());
@@ -1092,9 +1093,9 @@ class CategoricalBlock : public PandasBlock {
for (int c = 0; c < data.num_chunks(); c++) {
const std::shared_ptr<Array> arr = data.chunk(c);
- const auto& dict_arr = static_cast<const DictionaryArray&>(*arr);
+ const auto& dict_arr = checked_cast<const DictionaryArray&>(*arr);
- const auto& indices = static_cast<const ArrayType&>(*dict_arr.indices());
+ const auto& indices = checked_cast<const ArrayType&>(*dict_arr.indices());
auto in_values = reinterpret_cast<const T*>(indices.raw_values());
RETURN_NOT_OK(CheckIndices(indices, dict_arr.dictionary()->length()));
@@ -1125,7 +1126,7 @@ class CategoricalBlock : public PandasBlock {
converted_col = col;
}
- const auto& dict_type = static_cast<const DictionaryType&>(*converted_col->type());
+ const auto& dict_type = checked_cast<const DictionaryType&>(*converted_col->type());
switch (dict_type.index_type()->id()) {
case Type::INT8:
@@ -1327,7 +1328,7 @@ static Status GetPandasBlockType(const Column& col, const PandasOptions& options
*output_type = PandasBlock::DATETIME;
break;
case Type::TIMESTAMP: {
- const auto& ts_type = static_cast<const TimestampType&>(*col.type());
+ const auto& ts_type = checked_cast<const TimestampType&>(*col.type());
if (ts_type.timezone() != "") {
*output_type = PandasBlock::DATETIME_WITH_TZ;
} else {
@@ -1393,7 +1394,7 @@ class DataFrameBlockCreator {
block = std::make_shared<CategoricalBlock>(options_, pool_, table_->num_rows());
categorical_blocks_[i] = block;
} else if (output_type == PandasBlock::DATETIME_WITH_TZ) {
- const auto& ts_type = static_cast<const TimestampType&>(*col->type());
+ const auto& ts_type = checked_cast<const TimestampType&>(*col->type());
block = std::make_shared<DatetimeTZBlock>(options_, ts_type.timezone(),
table_->num_rows());
RETURN_NOT_OK(block->Allocate());
diff --git a/cpp/src/arrow/python/arrow_to_python.cc b/cpp/src/arrow/python/arrow_to_python.cc
index 6ae5d43..57884e5 100644
--- a/cpp/src/arrow/python/arrow_to_python.cc
+++ b/cpp/src/arrow/python/arrow_to_python.cc
@@ -33,6 +33,7 @@
#include "arrow/io/memory.h"
#include "arrow/ipc/reader.h"
#include "arrow/table.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include "arrow/python/common.h"
@@ -63,7 +64,7 @@ Status DeserializeSet(PyObject* context, const Array& array, int64_t start_idx,
Status DeserializeDict(PyObject* context, const Array& array, int64_t start_idx,
int64_t stop_idx, PyObject* base, const SerializedPyObject& blobs,
PyObject** out) {
- const auto& data = static_cast<const StructArray&>(array);
+ const auto& data = checked_cast<const StructArray&>(array);
OwnedRef keys, vals;
OwnedRef result(PyDict_New());
RETURN_IF_PYERROR();
@@ -93,7 +94,7 @@ Status DeserializeDict(PyObject* context, const Array& array, int64_t start_idx,
Status DeserializeArray(const Array& array, int64_t offset, PyObject* base,
const SerializedPyObject& blobs, PyObject** out) {
- int32_t index = static_cast<const Int32Array&>(array).Value(offset);
+ int32_t index = checked_cast<const Int32Array&>(array).Value(offset);
RETURN_NOT_OK(py::TensorToNdarray(blobs.tensors[index], base, out));
// Mark the array as immutable
OwnedRef flags(PyObject_GetAttrString(*out, "flags"));
@@ -109,43 +110,43 @@ Status GetValue(PyObject* context, const UnionArray& parent, const Array& arr,
const SerializedPyObject& blobs, PyObject** result) {
switch (arr.type()->id()) {
case Type::BOOL:
- *result = PyBool_FromLong(static_cast<const BooleanArray&>(arr).Value(index));
+ *result = PyBool_FromLong(checked_cast<const BooleanArray&>(arr).Value(index));
return Status::OK();
case Type::INT64:
- *result = PyLong_FromSsize_t(static_cast<const Int64Array&>(arr).Value(index));
+ *result = PyLong_FromSsize_t(checked_cast<const Int64Array&>(arr).Value(index));
return Status::OK();
case Type::BINARY: {
int32_t nchars;
- const uint8_t* str = static_cast<const BinaryArray&>(arr).GetValue(index, &nchars);
+ const uint8_t* str = checked_cast<const BinaryArray&>(arr).GetValue(index, &nchars);
*result = PyBytes_FromStringAndSize(reinterpret_cast<const char*>(str), nchars);
return CheckPyError();
}
case Type::STRING: {
int32_t nchars;
- const uint8_t* str = static_cast<const StringArray&>(arr).GetValue(index, &nchars);
+ const uint8_t* str = checked_cast<const StringArray&>(arr).GetValue(index, &nchars);
*result = PyUnicode_FromStringAndSize(reinterpret_cast<const char*>(str), nchars);
return CheckPyError();
}
case Type::HALF_FLOAT: {
- *result = PyHalf_FromHalf(static_cast<const HalfFloatArray&>(arr).Value(index));
+ *result = PyHalf_FromHalf(checked_cast<const HalfFloatArray&>(arr).Value(index));
RETURN_IF_PYERROR();
return Status::OK();
}
case Type::FLOAT:
- *result = PyFloat_FromDouble(static_cast<const FloatArray&>(arr).Value(index));
+ *result = PyFloat_FromDouble(checked_cast<const FloatArray&>(arr).Value(index));
return Status::OK();
case Type::DOUBLE:
- *result = PyFloat_FromDouble(static_cast<const DoubleArray&>(arr).Value(index));
+ *result = PyFloat_FromDouble(checked_cast<const DoubleArray&>(arr).Value(index));
return Status::OK();
case Type::DATE64: {
- RETURN_NOT_OK(PyDateTime_from_int(static_cast<const Date64Array&>(arr).Value(index),
- TimeUnit::MICRO, result));
+ RETURN_NOT_OK(PyDateTime_from_int(
+ checked_cast<const Date64Array&>(arr).Value(index), TimeUnit::MICRO, result));
RETURN_IF_PYERROR();
return Status::OK();
}
case Type::STRUCT: {
- const auto& s = static_cast<const StructArray&>(arr);
- const auto& l = static_cast<const ListArray&>(*s.field(0));
+ const auto& s = checked_cast<const StructArray&>(arr);
+ const auto& l = checked_cast<const ListArray&>(*s.field(0));
if (s.type()->child(0)->name() == "list") {
return DeserializeList(context, *l.values(), l.value_offset(index),
l.value_offset(index + 1), base, blobs, result);
@@ -167,7 +168,7 @@ Status GetValue(PyObject* context, const UnionArray& parent, const Array& arr,
if (child_name == "tensor") {
return DeserializeArray(arr, index, base, blobs, result);
} else if (child_name == "buffer") {
- int32_t ref = static_cast<const Int32Array&>(arr).Value(index);
+ int32_t ref = checked_cast<const Int32Array&>(arr).Value(index);
*result = wrap_buffer(blobs.buffers[ref]);
return Status::OK();
} else {
@@ -180,7 +181,7 @@ Status GetValue(PyObject* context, const UnionArray& parent, const Array& arr,
}
#define DESERIALIZE_SEQUENCE(CREATE_FN, SET_ITEM_FN) \
- const auto& data = static_cast<const UnionArray&>(array); \
+ const auto& data = checked_cast<const UnionArray&>(array); \
OwnedRef result(CREATE_FN(stop_idx - start_idx)); \
const uint8_t* type_ids = data.raw_type_ids(); \
const int32_t* value_offsets = data.raw_value_offsets(); \
@@ -215,7 +216,7 @@ Status DeserializeTuple(PyObject* context, const Array& array, int64_t start_idx
Status DeserializeSet(PyObject* context, const Array& array, int64_t start_idx,
int64_t stop_idx, PyObject* base, const SerializedPyObject& blobs,
PyObject** out) {
- const auto& data = static_cast<const UnionArray&>(array);
+ const auto& data = checked_cast<const UnionArray&>(array);
OwnedRef result(PySet_New(nullptr));
const uint8_t* type_ids = data.raw_type_ids();
const int32_t* value_offsets = data.raw_value_offsets();
diff --git a/cpp/src/arrow/python/builtin_convert.cc b/cpp/src/arrow/python/builtin_convert.cc
index 88674d0..dc0ae8c 100644
--- a/cpp/src/arrow/python/builtin_convert.cc
+++ b/cpp/src/arrow/python/builtin_convert.cc
@@ -31,6 +31,7 @@
#include "arrow/api.h"
#include "arrow/status.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/logging.h"
@@ -351,8 +352,10 @@ template <typename BuilderType>
class TypedConverter : public SeqConverter {
public:
Status Init(ArrayBuilder* builder) override {
- builder_ = builder;
- typed_builder_ = static_cast<BuilderType*>(builder);
+ RETURN_NOT_OK(SeqConverter::Init(builder));
+ DCHECK_NE(builder_, nullptr);
+ typed_builder_ = checked_cast<BuilderType*>(builder);
+ DCHECK_NE(typed_builder_, nullptr);
return Status::OK();
}
@@ -366,7 +369,7 @@ template <typename BuilderType, class Derived>
class TypedConverterVisitor : public TypedConverter<BuilderType> {
public:
Status AppendSingle(PyObject* obj) override {
- auto self = static_cast<Derived*>(this);
+ auto self = checked_cast<Derived*>(this);
return self->IsNull(obj) ? self->AppendNull() : self->AppendItem(obj);
}
@@ -374,7 +377,7 @@ class TypedConverterVisitor : public TypedConverter<BuilderType> {
/// Ensure we've allocated enough space
RETURN_NOT_OK(this->typed_builder_->Reserve(size));
// Iterate over the items adding each one
- auto self = static_cast<Derived*>(this);
+ auto self = checked_cast<Derived*>(this);
auto visit = [self](PyObject* item) { return self->AppendSingle(item); };
return internal::VisitSequence(obj, visit);
}
@@ -480,7 +483,7 @@ class TimestampConverter
ss << type->ToString();
return Status::Invalid(ss.str());
}
- const TimestampType& ttype = static_cast<const TimestampType&>(*type);
+ const TimestampType& ttype = checked_cast<const TimestampType&>(*type);
if (unit_ != ttype.unit()) {
return Status::NotImplemented(
"Cannot convert NumPy datetime64 objects with differing unit");
@@ -642,7 +645,7 @@ class DecimalConverter
// Append a non-missing item
Status AppendItem(PyObject* obj) {
Decimal128 value;
- const auto& type = static_cast<const DecimalType&>(*typed_builder_->type());
+ const auto& type = checked_cast<const DecimalType&>(*typed_builder_->type());
RETURN_NOT_OK(internal::DecimalFromPythonDecimal(obj, type, &value));
return typed_builder_->Append(value);
}
@@ -677,7 +680,7 @@ std::unique_ptr<SeqConverter> GetConverter(const std::shared_ptr<DataType>& type
return std::unique_ptr<SeqConverter>(new Date64Converter);
case Type::TIMESTAMP:
return std::unique_ptr<SeqConverter>(
- new TimestampConverter(static_cast<const TimestampType&>(*type).unit()));
+ new TimestampConverter(checked_cast<const TimestampType&>(*type).unit()));
case Type::HALF_FLOAT:
return std::unique_ptr<SeqConverter>(new Float16Converter);
case Type::FLOAT:
@@ -703,10 +706,10 @@ std::unique_ptr<SeqConverter> GetConverter(const std::shared_ptr<DataType>& type
Status ListConverter::Init(ArrayBuilder* builder) {
builder_ = builder;
- typed_builder_ = static_cast<ListBuilder*>(builder);
+ typed_builder_ = checked_cast<ListBuilder*>(builder);
value_converter_ =
- GetConverter(static_cast<ListType*>(builder->type().get())->value_type());
+ GetConverter(checked_cast<const ListType&>(*builder->type()).value_type());
if (value_converter_ == nullptr) {
return Status::NotImplemented("value type not implemented");
}
@@ -716,19 +719,19 @@ Status ListConverter::Init(ArrayBuilder* builder) {
Status StructConverter::Init(ArrayBuilder* builder) {
builder_ = builder;
- typed_builder_ = static_cast<StructBuilder*>(builder);
- StructType* struct_type = static_cast<StructType*>(builder->type().get());
+ typed_builder_ = checked_cast<StructBuilder*>(builder);
+ const auto& struct_type = checked_cast<const StructType&>(*builder->type());
num_fields_ = typed_builder_->num_fields();
- DCHECK_EQ(num_fields_, struct_type->num_children());
+ DCHECK_EQ(num_fields_, struct_type.num_children());
field_name_list_.reset(PyList_New(num_fields_));
RETURN_IF_PYERROR();
// Initialize the child converters and field names
for (int i = 0; i < num_fields_; i++) {
- const std::string& field_name(struct_type->child(i)->name());
- std::shared_ptr<DataType> field_type(struct_type->child(i)->type());
+ const std::string& field_name(struct_type.child(i)->name());
+ std::shared_ptr<DataType> field_type(struct_type.child(i)->type());
auto value_converter = GetConverter(field_type);
if (value_converter == nullptr) {
diff --git a/cpp/src/arrow/python/helpers.cc b/cpp/src/arrow/python/helpers.cc
index bb0837c..b96d5ff 100644
--- a/cpp/src/arrow/python/helpers.cc
+++ b/cpp/src/arrow/python/helpers.cc
@@ -23,6 +23,7 @@
#include "arrow/python/common.h"
#include "arrow/python/decimal.h"
#include "arrow/python/helpers.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
#include <arrow/api.h>
@@ -179,7 +180,7 @@ Status BuilderAppend(FixedSizeBinaryBuilder* builder, PyObject* obj, bool* is_fu
// XXX For some reason, we must accept unicode objects here
RETURN_NOT_OK(view.FromString(obj));
const auto expected_length =
- static_cast<const FixedSizeBinaryType&>(*builder->type()).byte_width();
+ checked_cast<const FixedSizeBinaryType&>(*builder->type()).byte_width();
if (ARROW_PREDICT_FALSE(view.size != expected_length)) {
std::stringstream ss;
ss << "Got bytestring of length " << view.size << " (expected " << expected_length
diff --git a/cpp/src/arrow/python/numpy_to_arrow.cc b/cpp/src/arrow/python/numpy_to_arrow.cc
index 646fb74..793c318 100644
--- a/cpp/src/arrow/python/numpy_to_arrow.cc
+++ b/cpp/src/arrow/python/numpy_to_arrow.cc
@@ -38,6 +38,7 @@
#include "arrow/type_fwd.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit-util.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/decimal.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
@@ -758,7 +759,7 @@ Status NumPyConverter::ConvertDecimals() {
Decimal128Builder builder(type_, pool_);
RETURN_NOT_OK(builder.Resize(length_));
- const auto& decimal_type = static_cast<const DecimalType&>(*type_);
+ const auto& decimal_type = checked_cast<const DecimalType&>(*type_);
for (PyObject* object : objects) {
const int is_decimal = PyObject_IsInstance(object, decimal_type_.obj());
@@ -983,7 +984,7 @@ Status NumPyConverter::ConvertObjectFixedWidthBytes(
const std::shared_ptr<DataType>& type) {
PyAcquireGIL lock;
- const int32_t byte_width = static_cast<const FixedSizeBinaryType&>(*type).byte_width();
+ const int32_t byte_width = checked_cast<const FixedSizeBinaryType&>(*type).byte_width();
// The output type at this point is inconclusive because there may be bytes
// and unicode mixed in the object array
@@ -1158,7 +1159,7 @@ Status NumPyConverter::ConvertObjects() {
case Type::DATE64:
return ConvertDates<Date64Type>();
case Type::LIST: {
- const auto& list_field = static_cast<const ListType&>(*type_);
+ const auto& list_field = checked_cast<const ListType&>(*type_);
return ConvertLists(list_field.value_field()->type());
}
case Type::DECIMAL:
@@ -1204,7 +1205,7 @@ inline Status NumPyConverter::ConvertTypedLists(const std::shared_ptr<DataType>&
have_mask = true;
}
- BuilderT* value_builder = static_cast<BuilderT*>(builder->value_builder());
+ auto value_builder = checked_cast<BuilderT*>(builder->value_builder());
auto foreach_item = [&](PyObject* object, bool mask) {
if (mask || internal::PandasObjectIsNull(object)) {
@@ -1249,7 +1250,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, NullType>(
have_mask = true;
}
- auto value_builder = static_cast<NullBuilder*>(builder->value_builder());
+ auto value_builder = checked_cast<NullBuilder*>(builder->value_builder());
auto foreach_item = [&](PyObject* object, bool mask) {
if (mask || internal::PandasObjectIsNull(object)) {
@@ -1293,7 +1294,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, BinaryType>(
have_mask = true;
}
- auto value_builder = static_cast<BinaryBuilder*>(builder->value_builder());
+ auto value_builder = checked_cast<BinaryBuilder*>(builder->value_builder());
auto foreach_item = [&](PyObject* object, bool mask) {
if (mask || internal::PandasObjectIsNull(object)) {
@@ -1322,7 +1323,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, BinaryType>(
ss << inferred_type->ToString() << " cannot be converted to BINARY.";
return Status::TypeError(ss.str());
}
- return AppendPySequence(object, size, inferred_type, value_builder);
+ return AppendPySequence(object, size, type, value_builder);
} else {
return Status::TypeError("Unsupported Python type for list items");
}
@@ -1346,7 +1347,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, StringType>(
have_mask = true;
}
- auto value_builder = static_cast<StringBuilder*>(builder->value_builder());
+ auto value_builder = checked_cast<StringBuilder*>(builder->value_builder());
auto foreach_item = [&](PyObject* object, bool mask) {
if (mask || internal::PandasObjectIsNull(object)) {
@@ -1379,7 +1380,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, StringType>(
ss << inferred_type->ToString() << " cannot be converted to STRING.";
return Status::TypeError(ss.str());
}
- return AppendPySequence(object, size, inferred_type, value_builder);
+ return AppendPySequence(object, size, type, value_builder);
} else {
return Status::TypeError("Unsupported Python type for list items");
}
@@ -1412,8 +1413,8 @@ Status NumPyConverter::ConvertLists(const std::shared_ptr<DataType>& type,
LIST_CASE(BINARY, NPY_OBJECT, BinaryType)
LIST_CASE(STRING, NPY_OBJECT, StringType)
case Type::LIST: {
- const auto& list_type = static_cast<const ListType&>(*type);
- auto value_builder = static_cast<ListBuilder*>(builder->value_builder());
+ const auto& list_type = checked_cast<const ListType&>(*type);
+ auto value_builder = checked_cast<ListBuilder*>(builder->value_builder());
auto foreach_item = [this, &builder, &value_builder, &list_type](PyObject* object) {
if (internal::PandasObjectIsNull(object)) {
@@ -1438,7 +1439,7 @@ Status NumPyConverter::ConvertLists(const std::shared_ptr<DataType>& type,
Status NumPyConverter::ConvertLists(const std::shared_ptr<DataType>& type) {
std::unique_ptr<ArrayBuilder> array_builder;
RETURN_NOT_OK(MakeBuilder(pool_, arrow::list(type), &array_builder));
- ListBuilder* list_builder = static_cast<ListBuilder*>(array_builder.get());
+ auto list_builder = checked_cast<ListBuilder*>(array_builder.get());
RETURN_NOT_OK(ConvertLists(type, list_builder, reinterpret_cast<PyObject*>(arr_)));
return PushBuilderResult(list_builder);
}
diff --git a/cpp/src/arrow/python/python-test.cc b/cpp/src/arrow/python/python-test.cc
index 81d3fea..60da08b 100644
--- a/cpp/src/arrow/python/python-test.cc
+++ b/cpp/src/arrow/python/python-test.cc
@@ -30,6 +30,7 @@
#include "arrow/python/builtin_convert.h"
#include "arrow/python/decimal.h"
#include "arrow/python/helpers.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
namespace py {
@@ -276,7 +277,7 @@ TEST_F(DecimalTest, FromPythonDecimalRescaleNotTruncateable) {
Decimal128 value;
OwnedRef python_decimal(this->CreatePythonDecimal("1.001"));
auto type = ::arrow::decimal(10, 2);
- const auto& decimal_type = static_cast<const DecimalType&>(*type);
+ const auto& decimal_type = checked_cast<const DecimalType&>(*type);
ASSERT_RAISES(Invalid, internal::DecimalFromPythonDecimal(python_decimal.obj(),
decimal_type, &value));
}
@@ -287,7 +288,7 @@ TEST_F(DecimalTest, FromPythonDecimalRescaleTruncateable) {
Decimal128 value;
OwnedRef python_decimal(this->CreatePythonDecimal("1.000"));
auto type = ::arrow::decimal(10, 2);
- const auto& decimal_type = static_cast<const DecimalType&>(*type);
+ const auto& decimal_type = checked_cast<const DecimalType&>(*type);
ASSERT_OK(
internal::DecimalFromPythonDecimal(python_decimal.obj(), decimal_type, &value));
ASSERT_EQ(100, value.low_bits());
@@ -297,7 +298,7 @@ TEST_F(DecimalTest, FromPythonNegativeDecimalRescale) {
Decimal128 value;
OwnedRef python_decimal(this->CreatePythonDecimal("-1.000"));
auto type = ::arrow::decimal(10, 9);
- const auto& decimal_type = static_cast<const DecimalType&>(*type);
+ const auto& decimal_type = checked_cast<const DecimalType&>(*type);
ASSERT_OK(
internal::DecimalFromPythonDecimal(python_decimal.obj(), decimal_type, &value));
ASSERT_EQ(-1000000000, value);
@@ -313,7 +314,7 @@ TEST_F(DecimalTest, TestOverflowFails) {
ASSERT_EQ(1, metadata.scale());
auto type = ::arrow::decimal(38, 38);
- const auto& decimal_type = static_cast<const DecimalType&>(*type);
+ const auto& decimal_type = checked_cast<const DecimalType&>(*type);
ASSERT_RAISES(Invalid, internal::DecimalFromPythonDecimal(python_decimal.obj(),
decimal_type, &value));
}
@@ -373,7 +374,7 @@ TEST_F(DecimalTest, TestMixedPrecisionAndScale) {
MemoryPool* pool = default_memory_pool();
std::shared_ptr<Array> arr;
ASSERT_OK(ConvertPySequence(list, pool, &arr));
- const auto& type = static_cast<const DecimalType&>(*arr->type());
+ const auto& type = checked_cast<const DecimalType&>(*arr->type());
int32_t expected_precision = 9;
int32_t expected_scale = 3;
@@ -402,7 +403,7 @@ TEST_F(DecimalTest, TestMixedPrecisionAndScaleSequenceConvert) {
ASSERT_OK(ConvertPySequence(list, pool, &arr));
- const auto& type = static_cast<const Decimal128Type&>(*arr->type());
+ const auto& type = checked_cast<const Decimal128Type&>(*arr->type());
ASSERT_EQ(3, type.precision());
ASSERT_EQ(3, type.scale());
}
diff --git a/cpp/src/arrow/status.cc b/cpp/src/arrow/status.cc
index 9b509b4..c2f2f18 100644
--- a/cpp/src/arrow/status.cc
+++ b/cpp/src/arrow/status.cc
@@ -33,7 +33,7 @@ void Status::CopyFrom(const State* state) {
}
std::string Status::CodeAsString() const {
- if (state_ == NULL) {
+ if (state_ == nullptr) {
return "OK";
}
diff --git a/cpp/src/arrow/table_builder-test.cc b/cpp/src/arrow/table_builder-test.cc
index 8167577..32d4bdb 100644
--- a/cpp/src/arrow/table_builder-test.cc
+++ b/cpp/src/arrow/table_builder-test.cc
@@ -29,6 +29,7 @@
#include "arrow/test-common.h"
#include "arrow/test-util.h"
#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
@@ -58,7 +59,7 @@ void AppendValues(BuilderType* builder, const std::vector<T>& values,
template <typename ValueType, typename T>
void AppendList(ListBuilder* builder, const std::vector<std::vector<T>>& values,
const std::vector<bool>& is_valid) {
- auto values_builder = static_cast<ValueType*>(builder->value_builder());
+ auto values_builder = checked_cast<ValueType*>(builder->value_builder());
for (size_t i = 0; i < values.size(); ++i) {
if (is_valid.size() == 0 || is_valid[i]) {
@@ -108,7 +109,7 @@ TEST_F(TestRecordBatchBuilder, Basics) {
const int kIter = 3;
for (int i = 0; i < kIter; ++i) {
AppendData(builder->GetFieldAs<Int32Builder>(0),
- static_cast<StringBuilder*>(builder->GetField(1)),
+ checked_cast<StringBuilder*>(builder->GetField(1)),
builder->GetFieldAs<ListBuilder>(2));
std::shared_ptr<RecordBatch> batch;
diff --git a/cpp/src/arrow/table_builder.h b/cpp/src/arrow/table_builder.h
index 582389b..8a13f4d 100644
--- a/cpp/src/arrow/table_builder.h
+++ b/cpp/src/arrow/table_builder.h
@@ -25,6 +25,7 @@
#include "arrow/status.h"
#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/visibility.h"
namespace arrow {
@@ -65,7 +66,7 @@ class RecordBatchBuilder {
/// \return pointer to template type
template <typename T>
T* GetFieldAs(int i) {
- return static_cast<T*>(raw_field_builders_[i]);
+ return checked_cast<T*>(raw_field_builders_[i]);
}
/// \brief Finish current batch and optionally reset
diff --git a/cpp/src/arrow/tensor.cc b/cpp/src/arrow/tensor.cc
index 465f724..b0b2b4b 100644
--- a/cpp/src/arrow/tensor.cc
+++ b/cpp/src/arrow/tensor.cc
@@ -27,6 +27,7 @@
#include "arrow/compare.h"
#include "arrow/status.h"
#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/logging.h"
namespace arrow {
@@ -73,7 +74,7 @@ Tensor::Tensor(const std::shared_ptr<DataType>& type, const std::shared_ptr<Buff
: type_(type), data_(data), shape_(shape), strides_(strides), dim_names_(dim_names) {
DCHECK(is_tensor_supported(type->id()));
if (shape.size() > 0 && strides.size() == 0) {
- ComputeRowMajorStrides(static_cast<const FixedWidthType&>(*type_), shape, &strides_);
+ ComputeRowMajorStrides(checked_cast<const FixedWidthType&>(*type_), shape, &strides_);
}
}
@@ -103,14 +104,14 @@ bool Tensor::is_contiguous() const { return is_row_major() || is_column_major();
bool Tensor::is_row_major() const {
std::vector<int64_t> c_strides;
- const auto& fw_type = static_cast<const FixedWidthType&>(*type_);
+ const auto& fw_type = checked_cast<const FixedWidthType&>(*type_);
ComputeRowMajorStrides(fw_type, shape_, &c_strides);
return strides_ == c_strides;
}
bool Tensor::is_column_major() const {
std::vector<int64_t> f_strides;
- const auto& fw_type = static_cast<const FixedWidthType&>(*type_);
+ const auto& fw_type = checked_cast<const FixedWidthType&>(*type_);
ComputeColumnMajorStrides(fw_type, shape_, &f_strides);
return strides_ == f_strides;
}
diff --git a/cpp/src/arrow/type-test.cc b/cpp/src/arrow/type-test.cc
index e9245d5..542e361 100644
--- a/cpp/src/arrow/type-test.cc
+++ b/cpp/src/arrow/type-test.cc
@@ -26,6 +26,7 @@
#include "arrow/test-util.h"
#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/key_value_metadata.h"
using std::shared_ptr;
@@ -309,8 +310,8 @@ TEST(TestDateTypes, Attrs) {
ASSERT_EQ("date32[day]", t1->ToString());
ASSERT_EQ("date64[ms]", t2->ToString());
- ASSERT_EQ(32, static_cast<const FixedWidthType&>(*t1).bit_width());
- ASSERT_EQ(64, static_cast<const FixedWidthType&>(*t2).bit_width());
+ ASSERT_EQ(32, checked_cast<const FixedWidthType&>(*t1).bit_width());
+ ASSERT_EQ(64, checked_cast<const FixedWidthType&>(*t2).bit_width());
}
TEST(TestTimeType, Equals) {
diff --git a/cpp/src/arrow/type.cc b/cpp/src/arrow/type.cc
index 2f6e718..ba84059 100644
--- a/cpp/src/arrow/type.cc
+++ b/cpp/src/arrow/type.cc
@@ -26,6 +26,7 @@
#include "arrow/array.h"
#include "arrow/compare.h"
#include "arrow/status.h"
+#include "arrow/util/checked_cast.h"
#include "arrow/util/key_value_metadata.h"
#include "arrow/util/logging.h"
#include "arrow/util/stl.h"
@@ -255,7 +256,7 @@ DictionaryType::DictionaryType(const std::shared_ptr<DataType>& index_type,
ordered_(ordered) {}
int DictionaryType::bit_width() const {
- return static_cast<const FixedWidthType*>(index_type_.get())->bit_width();
+ return checked_cast<const FixedWidthType&>(*index_type_).bit_width();
}
std::shared_ptr<Array> DictionaryType::dictionary() const { return dictionary_; }
diff --git a/cpp/src/arrow/type.h b/cpp/src/arrow/type.h
index 915c0c7..2c5ec31 100644
--- a/cpp/src/arrow/type.h
+++ b/cpp/src/arrow/type.h
@@ -28,6 +28,7 @@
#include "arrow/status.h"
#include "arrow/type_fwd.h" // IWYU pragma: export
+#include "arrow/util/checked_cast.h"
#include "arrow/util/key_value_metadata.h"
#include "arrow/util/macros.h"
#include "arrow/util/visibility.h"
@@ -274,7 +275,7 @@ class ARROW_EXPORT CTypeImpl : public BASE {
int bit_width() const override { return static_cast<int>(sizeof(C_TYPE) * CHAR_BIT); }
Status Accept(TypeVisitor* visitor) const override {
- return visitor->Visit(*static_cast<const DERIVED*>(this));
+ return visitor->Visit(checked_cast<const DERIVED&>(*this));
}
std::string ToString() const override { return this->name(); }
diff --git a/cpp/src/arrow/util/CMakeLists.txt b/cpp/src/arrow/util/CMakeLists.txt
index 8969527..36cbd6d 100644
--- a/cpp/src/arrow/util/CMakeLists.txt
+++ b/cpp/src/arrow/util/CMakeLists.txt
@@ -53,6 +53,7 @@ if (ARROW_BUILD_BENCHMARKS)
endif()
ADD_ARROW_TEST(bit-util-test)
+ADD_ARROW_TEST(checked-cast-test)
ADD_ARROW_TEST(compression-test)
ADD_ARROW_TEST(decimal-test)
ADD_ARROW_TEST(key-value-metadata-test)
diff --git a/cpp/src/arrow/util/checked-cast-test.cc b/cpp/src/arrow/util/checked-cast-test.cc
new file mode 100644
index 0000000..4dc8438
--- /dev/null
+++ b/cpp/src/arrow/util/checked-cast-test.cc
@@ -0,0 +1,71 @@
+// 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 <type_traits>
+
+#include <gtest/gtest.h>
+
+#include "arrow/util/checked_cast.h"
+
+namespace arrow {
+
+class Foo {
+ public:
+ virtual ~Foo() = default;
+};
+
+class Bar {};
+class FooSub : public Foo {};
+template <typename T>
+class Baz : public Foo {};
+
+TEST(CheckedCast, TestInvalidSubclassCast) {
+ static_assert(std::is_polymorphic<Foo>::value, "Foo is not polymorphic");
+
+ Foo foo;
+ FooSub foosub;
+ const Foo& foosubref = foosub;
+ Baz<double> baz;
+ const Foo& bazref = baz;
+
+#ifndef NDEBUG // debug mode
+ // illegal pointer cast
+ ASSERT_EQ(nullptr, checked_cast<Bar*>(&foo));
+
+ // illegal reference cast
+ ASSERT_THROW(checked_cast<const Bar&>(foosubref), std::bad_cast);
+
+ // legal reference casts
+ ASSERT_NO_THROW(checked_cast<const FooSub&>(foosubref));
+ ASSERT_NO_THROW(checked_cast<const Baz<double>&>(bazref));
+#else // release mode
+ // failure modes for the invalid casts occur at compile time
+
+ // legal pointer cast
+ ASSERT_NE(nullptr, checked_cast<const FooSub*>(&foosubref));
+
+ // legal reference casts: this is static_cast in a release build, so ASSERT_NO_THROW
+ // doesn't make a whole lot of sense here.
+ auto& x = checked_cast<const FooSub&>(foosubref);
+ ASSERT_EQ(&foosubref, &x);
+
+ auto& y = checked_cast<const Baz<double>&>(bazref);
+ ASSERT_EQ(&bazref, &y);
+#endif
+}
+
+} // namespace arrow
diff --git a/cpp/src/arrow/util/hash.cc b/cpp/src/arrow/util/checked_cast.h
similarity index 54%
copy from cpp/src/arrow/util/hash.cc
copy to cpp/src/arrow/util/checked_cast.h
index 94ba524..d3714d8 100644
--- a/cpp/src/arrow/util/hash.cc
+++ b/cpp/src/arrow/util/checked_cast.h
@@ -15,24 +15,28 @@
// specific language governing permissions and limitations
// under the License.
-#include "arrow/util/hash.h"
+#ifndef ARROW_CAST_H
+#define ARROW_CAST_H
-#include "arrow/buffer.h"
-#include "arrow/status.h"
+#include <type_traits>
namespace arrow {
-namespace internal {
-Status NewHashTable(int64_t size, MemoryPool* pool, std::shared_ptr<Buffer>* out) {
- auto hash_table = std::make_shared<PoolBuffer>(pool);
-
- RETURN_NOT_OK(hash_table->Resize(sizeof(hash_slot_t) * size));
- int32_t* slots = reinterpret_cast<hash_slot_t*>(hash_table->mutable_data());
- std::fill(slots, slots + size, kHashSlotEmpty);
-
- *out = hash_table;
- return Status::OK();
+template <typename OutputType, typename InputType>
+inline OutputType checked_cast(InputType&& value) {
+ static_assert(std::is_class<typename std::remove_pointer<
+ typename std::remove_reference<InputType>::type>::type>::value,
+ "checked_cast input type must be a class");
+ static_assert(std::is_class<typename std::remove_pointer<
+ typename std::remove_reference<OutputType>::type>::type>::value,
+ "checked_cast output type must be a class");
+#ifdef NDEBUG
+ return static_cast<OutputType>(value);
+#else
+ return dynamic_cast<OutputType>(value);
+#endif
}
-} // namespace internal
} // namespace arrow
+
+#endif // ARROW_CAST_H
diff --git a/cpp/src/arrow/util/hash.cc b/cpp/src/arrow/util/hash.cc
index 94ba524..4f2f1a2 100644
--- a/cpp/src/arrow/util/hash.cc
+++ b/cpp/src/arrow/util/hash.cc
@@ -27,7 +27,7 @@ Status NewHashTable(int64_t size, MemoryPool* pool, std::shared_ptr<Buffer>* out
auto hash_table = std::make_shared<PoolBuffer>(pool);
RETURN_NOT_OK(hash_table->Resize(sizeof(hash_slot_t) * size));
- int32_t* slots = reinterpret_cast<hash_slot_t*>(hash_table->mutable_data());
+ auto slots = reinterpret_cast<hash_slot_t*>(hash_table->mutable_data());
std::fill(slots, slots + size, kHashSlotEmpty);
*out = hash_table;
diff --git a/cpp/src/arrow/visitor_inline.h b/cpp/src/arrow/visitor_inline.h
index 41b0108..ae5307b 100644
--- a/cpp/src/arrow/visitor_inline.h
+++ b/cpp/src/arrow/visitor_inline.h
@@ -24,12 +24,13 @@
#include "arrow/status.h"
#include "arrow/tensor.h"
#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
namespace arrow {
#define TYPE_VISIT_INLINE(TYPE_CLASS) \
case TYPE_CLASS::type_id: \
- return visitor->Visit(static_cast<const TYPE_CLASS&>(type));
+ return visitor->Visit(checked_cast<const TYPE_CLASS&>(type));
template <typename VISITOR>
inline Status VisitTypeInline(const DataType& type, VISITOR* visitor) {
@@ -71,7 +72,7 @@ inline Status VisitTypeInline(const DataType& type, VISITOR* visitor) {
#define ARRAY_VISIT_INLINE(TYPE_CLASS) \
case TYPE_CLASS::type_id: \
return visitor->Visit( \
- static_cast<const typename TypeTraits<TYPE_CLASS>::ArrayType&>(array));
+ checked_cast<const typename TypeTraits<TYPE_CLASS>::ArrayType&>(array));
template <typename VISITOR>
inline Status VisitArrayInline(const Array& array, VISITOR* visitor) {
diff --git a/python/pyarrow/tests/pandas_examples.py b/python/pyarrow/tests/pandas_examples.py
index f11da3c..65791d4 100644
--- a/python/pyarrow/tests/pandas_examples.py
+++ b/python/pyarrow/tests/pandas_examples.py
@@ -98,7 +98,7 @@ def dataframe_with_lists(include_index=False):
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4],
None,
- [0],
+ [],
np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 2,
dtype=np.int64)[::2]
]
@@ -107,7 +107,7 @@ def dataframe_with_lists(include_index=False):
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4.],
None,
- [0.],
+ [],
np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.] * 2)[::2],
]
fields.append(pa.field('bytes_list', pa.list_(pa.binary())))
--
To stop receiving notification emails like this one, please contact
uwe@apache.org.