|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
#include <cstdint> |
|
#include <memory> |
|
#include <type_traits> |
|
#include <vector> |
|
|
|
#include "arrow/array.h" |
|
#include "arrow/array/builder_binary.h" |
|
#include "arrow/array/builder_primitive.h" |
|
#include "arrow/array/builder_time.h" |
|
#include "arrow/buffer.h" |
|
#include "arrow/testing/gtest_util.h" |
|
#include "arrow/type_fwd.h" |
|
#include "arrow/util/bit_util.h" |
|
#include "arrow/visit_type_inline.h" |
|
|
|
namespace arrow { |
|
|
|
|
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ArrayFromVector(const std::shared_ptr<DataType>& type, |
|
const std::vector<bool>& is_valid, const std::vector<C_TYPE>& values, |
|
std::shared_ptr<Array>* out) { |
|
auto type_id = TYPE::type_id; |
|
ASSERT_EQ(type_id, type->id()) |
|
<< "template parameter and concrete DataType instance don't agree"; |
|
|
|
std::unique_ptr<ArrayBuilder> builder_ptr; |
|
ASSERT_OK(MakeBuilder(default_memory_pool(), type, &builder_ptr)); |
|
|
|
auto& builder = dynamic_cast<typename TypeTraits<TYPE>::BuilderType&>(*builder_ptr); |
|
|
|
for (size_t i = 0; i < values.size(); ++i) { |
|
if (is_valid[i]) { |
|
ASSERT_OK(builder.Append(values[i])); |
|
} else { |
|
ASSERT_OK(builder.AppendNull()); |
|
} |
|
} |
|
ASSERT_OK(builder.Finish(out)); |
|
} |
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ArrayFromVector(const std::shared_ptr<DataType>& type, |
|
const std::vector<C_TYPE>& values, std::shared_ptr<Array>* out) { |
|
auto type_id = TYPE::type_id; |
|
ASSERT_EQ(type_id, type->id()) |
|
<< "template parameter and concrete DataType instance don't agree"; |
|
|
|
std::unique_ptr<ArrayBuilder> builder_ptr; |
|
ASSERT_OK(MakeBuilder(default_memory_pool(), type, &builder_ptr)); |
|
|
|
auto& builder = dynamic_cast<typename TypeTraits<TYPE>::BuilderType&>(*builder_ptr); |
|
|
|
for (size_t i = 0; i < values.size(); ++i) { |
|
ASSERT_OK(builder.Append(values[i])); |
|
} |
|
ASSERT_OK(builder.Finish(out)); |
|
} |
|
|
|
|
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ArrayFromVector(const std::vector<bool>& is_valid, const std::vector<C_TYPE>& values, |
|
std::shared_ptr<Array>* out) { |
|
auto type = TypeTraits<TYPE>::type_singleton(); |
|
ArrayFromVector<TYPE, C_TYPE>(type, is_valid, values, out); |
|
} |
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ArrayFromVector(const std::vector<C_TYPE>& values, std::shared_ptr<Array>* out) { |
|
auto type = TypeTraits<TYPE>::type_singleton(); |
|
ArrayFromVector<TYPE, C_TYPE>(type, values, out); |
|
} |
|
|
|
|
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ChunkedArrayFromVector(const std::shared_ptr<DataType>& type, |
|
const std::vector<std::vector<bool>>& is_valid, |
|
const std::vector<std::vector<C_TYPE>>& values, |
|
std::shared_ptr<ChunkedArray>* out) { |
|
ArrayVector chunks; |
|
ASSERT_EQ(is_valid.size(), values.size()); |
|
for (size_t i = 0; i < values.size(); ++i) { |
|
std::shared_ptr<Array> array; |
|
ArrayFromVector<TYPE, C_TYPE>(type, is_valid[i], values[i], &array); |
|
chunks.push_back(array); |
|
} |
|
*out = std::make_shared<ChunkedArray>(chunks); |
|
} |
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ChunkedArrayFromVector(const std::shared_ptr<DataType>& type, |
|
const std::vector<std::vector<C_TYPE>>& values, |
|
std::shared_ptr<ChunkedArray>* out) { |
|
ArrayVector chunks; |
|
for (size_t i = 0; i < values.size(); ++i) { |
|
std::shared_ptr<Array> array; |
|
ArrayFromVector<TYPE, C_TYPE>(type, values[i], &array); |
|
chunks.push_back(array); |
|
} |
|
*out = std::make_shared<ChunkedArray>(chunks); |
|
} |
|
|
|
|
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ChunkedArrayFromVector(const std::vector<std::vector<bool>>& is_valid, |
|
const std::vector<std::vector<C_TYPE>>& values, |
|
std::shared_ptr<ChunkedArray>* out) { |
|
auto type = TypeTraits<TYPE>::type_singleton(); |
|
ChunkedArrayFromVector<TYPE, C_TYPE>(type, is_valid, values, out); |
|
} |
|
|
|
template <typename TYPE, typename C_TYPE = typename TYPE::c_type> |
|
void ChunkedArrayFromVector(const std::vector<std::vector<C_TYPE>>& values, |
|
std::shared_ptr<ChunkedArray>* out) { |
|
auto type = TypeTraits<TYPE>::type_singleton(); |
|
ChunkedArrayFromVector<TYPE, C_TYPE>(type, values, out); |
|
} |
|
|
|
template <typename BuilderType> |
|
void FinishAndCheckPadding(BuilderType* builder, std::shared_ptr<Array>* out) { |
|
ASSERT_OK_AND_ASSIGN(*out, builder->Finish()); |
|
AssertZeroPadded(**out); |
|
TestInitialized(**out); |
|
} |
|
|
|
template <class T, class Builder> |
|
Status MakeArray(const std::vector<uint8_t>& valid_bytes, const std::vector<T>& values, |
|
int64_t size, Builder* builder, std::shared_ptr<Array>* out) { |
|
|
|
for (int64_t i = 0; i < size; ++i) { |
|
if (valid_bytes[i] > 0) { |
|
RETURN_NOT_OK(builder->Append(values[i])); |
|
} else { |
|
RETURN_NOT_OK(builder->AppendNull()); |
|
} |
|
} |
|
return builder->Finish(out); |
|
} |
|
|
|
template <typename Fn> |
|
struct VisitBuilder { |
|
template <typename T, typename BuilderType = typename TypeTraits<T>::BuilderType, |
|
|
|
|
|
typename = decltype(std::declval<Fn>()(std::declval<BuilderType*>()))> |
|
Status Visit(const T&, ArrayBuilder* builder, Fn&& fn) { |
|
fn(internal::checked_cast<BuilderType*>(builder)); |
|
return Status::OK(); |
|
} |
|
|
|
Status Visit(const DataType& t, ArrayBuilder* builder, Fn&& fn) { |
|
return Status::NotImplemented("visiting builders of type ", t); |
|
} |
|
}; |
|
|
|
template <typename Fn> |
|
Result<std::shared_ptr<Array>> ArrayFromBuilderVisitor( |
|
const std::shared_ptr<DataType>& type, int64_t initial_capacity, |
|
int64_t visitor_repetitions, Fn&& fn) { |
|
std::unique_ptr<ArrayBuilder> builder; |
|
RETURN_NOT_OK(MakeBuilder(default_memory_pool(), type, &builder)); |
|
|
|
if (initial_capacity != 0) { |
|
RETURN_NOT_OK(builder->Resize(initial_capacity)); |
|
} |
|
|
|
VisitBuilder<Fn> visitor; |
|
for (int64_t i = 0; i < visitor_repetitions; ++i) { |
|
RETURN_NOT_OK( |
|
VisitTypeInline(*builder->type(), &visitor, builder.get(), std::forward<Fn>(fn))); |
|
} |
|
|
|
std::shared_ptr<Array> out; |
|
RETURN_NOT_OK(builder->Finish(&out)); |
|
return out; |
|
} |
|
|
|
template <typename Fn> |
|
Result<std::shared_ptr<Array>> ArrayFromBuilderVisitor( |
|
const std::shared_ptr<DataType>& type, int64_t length, Fn&& fn) { |
|
return ArrayFromBuilderVisitor(type, length, length, std::forward<Fn>(fn)); |
|
} |
|
|
|
template <typename T> |
|
static inline Status GetBitmapFromVector(const std::vector<T>& is_valid, |
|
std::shared_ptr<Buffer>* result) { |
|
size_t length = is_valid.size(); |
|
|
|
ARROW_ASSIGN_OR_RAISE(auto buffer, AllocateEmptyBitmap(length)); |
|
|
|
uint8_t* bitmap = buffer->mutable_data(); |
|
for (size_t i = 0; i < static_cast<size_t>(length); ++i) { |
|
if (is_valid[i]) { |
|
bit_util::SetBit(bitmap, i); |
|
} |
|
} |
|
|
|
*result = buffer; |
|
return Status::OK(); |
|
} |
|
|
|
template <typename T> |
|
inline void BitmapFromVector(const std::vector<T>& is_valid, |
|
std::shared_ptr<Buffer>* out) { |
|
ASSERT_OK(GetBitmapFromVector(is_valid, out)); |
|
} |
|
|
|
} |
|
|