| 92 | /// \param input A LIST_VIEW or LARGE_LIST_VIEW array |
| 93 | template <typename offset_type> |
| 94 | int64_t MaxViewEnd(const ArraySpan& input) { |
| 95 | const auto values_length = input.child_data[0].length; |
| 96 | |
| 97 | const uint8_t* validity = input.buffers[0].data; |
| 98 | const auto* offsets = input.GetValues<offset_type>(1); |
| 99 | const auto* sizes = input.GetValues<offset_type>(2); |
| 100 | |
| 101 | #define MAXIMIZE_MAX_VIEW_END(i) \ |
| 102 | const auto offset = static_cast<int64_t>(offsets[i]); \ |
| 103 | const offset_type size = sizes[i]; \ |
| 104 | if (size > 0) { \ |
| 105 | const int64_t end = offset + size; \ |
| 106 | if (end > max_end) { \ |
| 107 | if (end == values_length) { \ |
| 108 | return values_length; \ |
| 109 | } \ |
| 110 | max_end = end; \ |
| 111 | } \ |
| 112 | } |
| 113 | |
| 114 | int64_t max_end = 0; |
| 115 | if (validity == nullptr) { |
| 116 | for (int64_t i = input.length - 1; i >= 0; --i) { |
| 117 | MAXIMIZE_MAX_VIEW_END(i); |
| 118 | } |
| 119 | } else { |
| 120 | ReverseSetBitRunReader reader(validity, input.offset, input.length); |
| 121 | while (true) { |
| 122 | const auto run = reader.NextRun(); |
| 123 | if (run.length == 0) { |
| 124 | break; |
| 125 | } |
| 126 | for (int64_t i = run.position + run.length - 1; i >= run.position; --i) { |
| 127 | MAXIMIZE_MAX_VIEW_END(i); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | return max_end; |
| 132 | |
| 133 | #undef MAXIMIZE_MAX_VIEW_END |
| 134 | } |
| 135 | |
| 136 | template <typename offset_type> |
| 137 | std::pair<int64_t, int64_t> RangeOfValuesUsedByListView(const ArraySpan& input) { |