blob: 56846abc765b4ac50f8f0dc3ed2a7e550d4dc954 [file] [log] [blame]
/*
* 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 "converters.hpp"
namespace red_arrow {
namespace {
class ValuesBuilder : private Converter, public arrow::ArrayVisitor {
public:
explicit ValuesBuilder(VALUE values)
: Converter(),
values_(values),
row_offset_(0) {
}
void build(const arrow::Array& array, VALUE rb_array) {
rb::protect([&] {
check_status(array.Accept(this),
"[array][values]");
return Qnil;
});
}
void build(const arrow::ChunkedArray& chunked_array,
VALUE rb_chunked_array) {
rb::protect([&] {
for (const auto& array : chunked_array.chunks()) {
check_status(array->Accept(this),
"[chunked-array][values]");
row_offset_ += array->length();
}
return Qnil;
});
}
#define VISIT(TYPE) \
arrow::Status Visit(const arrow::TYPE ## Array& array) override { \
convert(array); \
return arrow::Status::OK(); \
}
VISIT(Null)
VISIT(Boolean)
VISIT(Int8)
VISIT(Int16)
VISIT(Int32)
VISIT(Int64)
VISIT(UInt8)
VISIT(UInt16)
VISIT(UInt32)
VISIT(UInt64)
// TODO
// VISIT(HalfFloat)
VISIT(Float)
VISIT(Double)
VISIT(Binary)
VISIT(String)
VISIT(FixedSizeBinary)
VISIT(Date32)
VISIT(Date64)
VISIT(Time32)
VISIT(Time64)
VISIT(Timestamp)
// TODO
// VISIT(Interval)
VISIT(List)
VISIT(Struct)
VISIT(SparseUnion)
VISIT(DenseUnion)
VISIT(Dictionary)
VISIT(Decimal128)
VISIT(Decimal256)
// TODO
// VISIT(Extension)
#undef VISIT
private:
template <typename ArrayType>
void convert(const ArrayType& array) {
const auto n = array.length();
if (array.null_count() > 0) {
for (int64_t i = 0, ii = row_offset_; i < n; ++i, ++ii) {
auto value = Qnil;
if (!array.IsNull(i)) {
value = convert_value(array, i);
}
rb_ary_store(values_, ii, value);
}
} else {
for (int64_t i = 0, ii = row_offset_; i < n; ++i, ++ii) {
rb_ary_store(values_, ii, convert_value(array, i));
}
}
}
// Destination for converted values.
VALUE values_;
// The current row offset.
int64_t row_offset_;
};
}
VALUE
array_values(VALUE rb_array) {
auto garrow_array = GARROW_ARRAY(RVAL2GOBJ(rb_array));
auto array = garrow_array_get_raw(garrow_array).get();
const auto n_rows = array->length();
auto values = rb_ary_new_capa(n_rows);
try {
ValuesBuilder builder(values);
builder.build(*array, rb_array);
} catch (rb::State& state) {
state.jump();
}
return values;
}
VALUE
chunked_array_values(VALUE rb_chunked_array) {
auto garrow_chunked_array =
GARROW_CHUNKED_ARRAY(RVAL2GOBJ(rb_chunked_array));
auto chunked_array =
garrow_chunked_array_get_raw(garrow_chunked_array).get();
const auto n_rows = chunked_array->length();
auto values = rb_ary_new_capa(n_rows);
try {
ValuesBuilder builder(values);
builder.build(*chunked_array, rb_chunked_array);
} catch (rb::State& state) {
state.jump();
}
return values;
}
}