| 528 | |
| 529 | template <typename IndexCType, bool IsSigned = std::is_signed<IndexCType>::value> |
| 530 | static Status CheckIndexBoundsImpl(const ArraySpan& values, uint64_t upper_limit) { |
| 531 | // For unsigned integers, if the values array is larger than the maximum |
| 532 | // index value (e.g. especially for UINT8 / UINT16), then there is no need to |
| 533 | // boundscheck. |
| 534 | if (!IsSigned && |
| 535 | upper_limit > static_cast<uint64_t>(std::numeric_limits<IndexCType>::max())) { |
| 536 | return Status::OK(); |
| 537 | } |
| 538 | |
| 539 | const IndexCType* values_data = values.GetValues<IndexCType>(1); |
| 540 | const uint8_t* bitmap = values.buffers[0].data; |
| 541 | auto IsOutOfBounds = [&](IndexCType val) -> bool { |
| 542 | return ((IsSigned && val < 0) || |
| 543 | (val >= 0 && static_cast<uint64_t>(val) >= upper_limit)); |
| 544 | }; |
| 545 | return VisitSetBitRuns( |
| 546 | bitmap, values.offset, values.length, [&](int64_t offset, int64_t length) { |
| 547 | bool block_out_of_bounds = false; |
| 548 | for (int64_t i = 0; i < length; ++i) { |
| 549 | block_out_of_bounds |= IsOutOfBounds(values_data[offset + i]); |
| 550 | } |
| 551 | if (ARROW_PREDICT_FALSE(block_out_of_bounds)) { |
| 552 | for (int64_t i = 0; i < length; ++i) { |
| 553 | if (IsOutOfBounds(values_data[offset + i])) { |
| 554 | return Status::IndexError("Index ", ToChars(values_data[offset + i]), |
| 555 | " out of bounds"); |
| 556 | } |
| 557 | } |
| 558 | } |
| 559 | return Status::OK(); |
| 560 | }); |
| 561 | } |
| 562 | |
| 563 | /// \brief Branchless boundschecking of the values. Processes batches of |
| 564 | /// values at a time and shortcircuits when encountering an out-of-bounds |
nothing calls this directly
no test coverage detected