Skip to content

Commit

Permalink
More clang-tidy cleanups in writer.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd committed Sep 27, 2024
1 parent c0f4752 commit 2d95cad
Showing 1 changed file with 85 additions and 89 deletions.
174 changes: 85 additions & 89 deletions src/pantab/writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <chrono>
#include <set>
#include <utility>
#include <variant>

static auto GetHyperTypeFromArrowSchema(struct ArrowSchema *schema,
Expand Down Expand Up @@ -99,6 +100,23 @@ class InsertHelper {
virtual void InsertValueAtIndex(int64_t) {}

protected:
auto CheckNull(int64_t idx) const {
return ArrowArrayViewIsNull(array_view_.get(), idx);
}

template <typename T> auto InsertNull() {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<std:::string_view>{std::nullopt});
inserter_.add(std::optional<T>{});
}

auto GetArrayView() const { return array_view_.get(); }

template <typename T> auto InsertValue(T &&value) {
inserter_.add(std::forward<T>(value));
}

private:
hyperapi::Inserter &inserter_;
const struct ArrowArray *chunk_;
const struct ArrowSchema *schema_;
Expand All @@ -112,16 +130,13 @@ template <typename T> class IntegralInsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<T>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<T>();
return;
}

const int64_t value = ArrowArrayViewGetIntUnsafe(array_view_.get(), idx);
hyperapi::internal::ValueInserter{inserter_}.addValue(
static_cast<T>(value));
const int64_t value = ArrowArrayViewGetIntUnsafe(GetArrayView(), idx);
InsertValue(static_cast<T>(value));
}
};

Expand All @@ -130,16 +145,13 @@ class UInt32InsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<T>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<uint32_t>();
return;
}

const uint64_t value = ArrowArrayViewGetUIntUnsafe(array_view_.get(), idx);
hyperapi::internal::ValueInserter{inserter_}.addValue(
static_cast<uint32_t>(value));
const uint64_t value = ArrowArrayViewGetUIntUnsafe(GetArrayView(), idx);
InsertValue(static_cast<uint32_t>(value));
}
};

Expand All @@ -148,16 +160,13 @@ template <typename T> class FloatingInsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<T>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<T>();
return;
}

const double value = ArrowArrayViewGetDoubleUnsafe(array_view_.get(), idx);
hyperapi::internal::ValueInserter{inserter_}.addValue(
static_cast<T>(value));
const double value = ArrowArrayViewGetDoubleUnsafe(GetArrayView(), idx);
InsertValue(static_cast<T>(value));
}
};

Expand All @@ -166,18 +175,16 @@ class BinaryInsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<std:::string_view>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<hyperapi::ByteSpan>();
return;
}

const struct ArrowBufferView buffer_view =
ArrowArrayViewGetBytesUnsafe(array_view_.get(), idx);
ArrowArrayViewGetBytesUnsafe(GetArrayView(), idx);
const hyperapi::ByteSpan result{
buffer_view.data.as_uint8, static_cast<size_t>(buffer_view.size_bytes)};
hyperapi::internal::ValueInserter{inserter_}.addValue(result);
InsertValue(std::move(result));
}
};

Expand All @@ -186,23 +193,16 @@ template <typename OffsetT> class Utf8InsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<std:::string_view>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<hyperapi::string_view>();
return;
}

const struct ArrowBufferView buffer_view =
ArrowArrayViewGetBytesUnsafe(array_view_.get(), idx);
#if defined(_WIN32) && defined(_MSC_VER)
const std::string result{buffer_view.data.as_char,
static_cast<size_t>(buffer_view.size_bytes)};
#else
const std::string_view result{buffer_view.data.as_char,
static_cast<size_t>(buffer_view.size_bytes)};
#endif
hyperapi::internal::ValueInserter{inserter_}.addValue(result);
ArrowArrayViewGetBytesUnsafe(GetArrayView(), idx);
const hyperapi::string_view result{
buffer_view.data.as_char, static_cast<size_t>(buffer_view.size_bytes)};
InsertValue(std::move(result));
}
};

Expand All @@ -212,16 +212,14 @@ class Date32InsertHelper : public InsertHelper {

void InsertValueAtIndex(int64_t idx) override {
constexpr size_t elem_size = sizeof(int32_t);
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<timestamp_t>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<hyperapi::Date>();
return;
}

int32_t value{};
memcpy(&value,
array_view_->buffer_views[1].data.as_uint8 + (idx * elem_size),
GetArrayView()->buffer_views[1].data.as_uint8 + (idx * elem_size),
elem_size);

const std::chrono::duration<int32_t, std::ratio<86400>> dur{value};
Expand All @@ -232,11 +230,11 @@ class Date32InsertHelper : public InsertHelper {
const auto tt = std::chrono::system_clock::to_time_t(tp);

const struct tm utc_tm = *std::gmtime(&tt);
const hyperapi::Date dt{1900 + utc_tm.tm_year,
static_cast<int16_t>(1 + utc_tm.tm_mon),
static_cast<int16_t>(utc_tm.tm_mday)};
hyperapi::Date dt{1900 + utc_tm.tm_year,
static_cast<int16_t>(1 + utc_tm.tm_mon),
static_cast<int16_t>(utc_tm.tm_mday)};

hyperapi::internal::ValueInserter{inserter_}.addValue(dt);
InsertValue(std::move(dt));
}
};

Expand All @@ -249,14 +247,12 @@ template <enum ArrowTimeUnit TU> class TimeInsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<T>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<hyperapi::Time>();
return;
}

int64_t value = ArrowArrayViewGetIntUnsafe(array_view_.get(), idx);
int64_t value = ArrowArrayViewGetIntUnsafe(GetArrayView(), idx);
// TODO: check for overflow in these branches
if constexpr (TU == NANOARROW_TIME_UNIT_SECOND) {
value *= MicrosecondsPerSecond;
Expand All @@ -265,7 +261,7 @@ template <enum ArrowTimeUnit TU> class TimeInsertHelper : public InsertHelper {
} else if constexpr (TU == NANOARROW_TIME_UNIT_NANO) {
value /= NanosecondsPerMicrosecond;
}
hyperapi::internal::ValueInserter{inserter_}.addValue(value);
InsertValue(hyperapi::Time{static_cast<hyper_time_t>(value), {}});
}
};

Expand All @@ -274,18 +270,20 @@ class TimestampInsertHelper : public InsertHelper {
public:
using InsertHelper::InsertHelper;

using timestamp_t =
typename std::conditional<TZAware, hyperapi::OffsetTimestamp,
hyperapi::Timestamp>::type;

void InsertValueAtIndex(int64_t idx) override {
constexpr size_t elem_size = sizeof(int64_t);
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<timestamp_t>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<timestamp_t>();
return;
}

int64_t value{};
memcpy(&value,
array_view_->buffer_views[1].data.as_uint8 + (idx * elem_size),
GetArrayView()->buffer_views[1].data.as_uint8 + (idx * elem_size),
elem_size);

// TODO: need overflow checks here
Expand All @@ -301,12 +299,8 @@ class TimestampInsertHelper : public InsertHelper {
hyper_timestamp_t raw_timestamp =
static_cast<hyper_timestamp_t>(value + USEC_TABLEAU_TO_UNIX_EPOCH);

using timestamp_t =
typename std::conditional<TZAware, hyperapi::OffsetTimestamp,
hyperapi::Timestamp>::type;
const timestamp_t ts{raw_timestamp, {}};
hyperapi::internal::ValueInserter{inserter_}.addValue(
static_cast<timestamp_t>(ts));
InsertValue(std::move(static_cast<timestamp_t>(ts)));
}
};

Expand All @@ -315,25 +309,19 @@ class IntervalInsertHelper : public InsertHelper {
using InsertHelper::InsertHelper;

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<timestamp_t>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
if (CheckNull(idx)) {
InsertNull<hyperapi::Interval>();
return;
}

struct ArrowInterval arrow_interval {};
ArrowIntervalInit(&arrow_interval, NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO);
ArrowArrayViewGetIntervalUnsafe(array_view_.get(), idx, &arrow_interval);
ArrowArrayViewGetIntervalUnsafe(GetArrayView(), idx, &arrow_interval);
const auto usec = static_cast<int32_t>(arrow_interval.ns / 1000);

// Hyper has no template specialization to insert an interval; instead we
// must use their internal representation
hyperapi::Interval interval(0, arrow_interval.months, arrow_interval.days,
0, 0, 0, usec);
// hyperapi::Interval interval{0, arrow_interval.months,
// arrow_interval.days, 0, 0, 0, usec};
inserter_.add(interval);
InsertValue(std::move(interval));
}
};

Expand All @@ -348,17 +336,33 @@ class DecimalInsertHelper : public InsertHelper {
precision_(precision), scale_(scale) {}

void InsertValueAtIndex(int64_t idx) override {
if (ArrowArrayViewIsNull(array_view_.get(), idx)) {
// MSVC on cibuildwheel doesn't like this templated optional
// inserter_->add(std::optional<timestamp_t>{std::nullopt});
hyperapi::internal::ValueInserter{inserter_}.addNull();
constexpr auto PrecisionLimit = 39; // of-by-one error in solution?
if (precision_ >= PrecisionLimit) {
throw nb::value_error("Numeric precision may not exceed 38!");
}
if (scale_ >= PrecisionLimit) {
throw nb::value_error("Numeric scale may not exceed 38!");
}

if (CheckNull(idx)) {
std::visit(
[&](auto P, auto S) {
if constexpr (S() <= P()) {
InsertNull<hyperapi::Numeric<P(), S()>>();
return;
} else {
throw "unreachable";
}
},
to_integral_variant<PrecisionLimit>(precision_),
to_integral_variant<PrecisionLimit>(scale_));
return;
}

constexpr int32_t bitwidth = 128;
struct ArrowDecimal decimal {};
ArrowDecimalInit(&decimal, bitwidth, precision_, scale_);
ArrowArrayViewGetDecimalUnsafe(array_view_.get(), idx, &decimal);
ArrowArrayViewGetDecimalUnsafe(GetArrayView(), idx, &decimal);

struct ArrowBuffer buffer {};
ArrowBufferInit(&buffer);
Expand All @@ -385,19 +389,11 @@ class DecimalInsertHelper : public InsertHelper {
}
}

constexpr auto PrecisionLimit = 39; // of-by-one error in solution?
if (precision_ >= PrecisionLimit) {
throw nb::value_error("Numeric precision may not exceed 38!");
}
if (scale_ >= PrecisionLimit) {
throw nb::value_error("Numeric scale may not exceed 38!");
}

std::visit(
[&](auto P, auto S) {
if constexpr (S() <= P()) {
const auto value = hyperapi::Numeric<P(), S()>{str};
inserter_.add(value);
InsertValue(std::move(value));
return;
} else {
throw "unreachable";
Expand Down

0 comments on commit 2d95cad

Please sign in to comment.