\brief Relocate values according to a validity bitmap, to the left Non-null values should initially be densely packed at the right of the buffer. This method spreads the values out according to the given validity bitmap. Null entries are zero-initialized. \param[in, out] buffer the in-place buffer \param[in] byte_width the byte width of values \param[in] length total length of buffer including n
| 111 | /// \param[in] valid_bits bitmap data indicating position of valid slots |
| 112 | /// \param[in] valid_bits_offset offset into valid_bits |
| 113 | inline void SpacedExpandLeftward(uint8_t* buffer, int byte_width, int64_t length, |
| 114 | int64_t null_count, const uint8_t* valid_bits, |
| 115 | int64_t valid_bits_offset) { |
| 116 | // Point to start of values. |
| 117 | int64_t idx_decode = byte_width * null_count; |
| 118 | |
| 119 | // Depending on the number of nulls, some of the value slots in buffer may |
| 120 | // be uninitialized, and this will cause valgrind warnings / potentially UB |
| 121 | memset(buffer, 0, idx_decode); |
| 122 | |
| 123 | arrow::internal::SetBitRunReader reader(valid_bits, valid_bits_offset, length); |
| 124 | while (true) { |
| 125 | const auto run = reader.NextRun(); |
| 126 | if (run.length == 0) { |
| 127 | break; |
| 128 | } |
| 129 | if (idx_decode == run.position * byte_width) { |
| 130 | // We have come to the point where no more expansion is required: the remaining |
| 131 | // values are already in their final position. |
| 132 | return; |
| 133 | } |
| 134 | // Source and destination may overlap if run.length > 1 |
| 135 | memmove(buffer + run.position * byte_width, buffer + idx_decode, |
| 136 | run.length * byte_width); |
| 137 | idx_decode += run.length * byte_width; |
| 138 | } |
| 139 | |
| 140 | // Otherwise caller gave an incorrect null_count |
| 141 | assert(idx_decode == length * byte_width); |
| 142 | } |
| 143 | |
| 144 | } // namespace arrow::util::internal |
no test coverage detected