| 71 | |
| 72 | template <bool value> |
| 73 | void SetBitmapImpl(uint8_t* data, int64_t offset, int64_t length) { |
| 74 | // offset length |
| 75 | // data |<------------->| |
| 76 | // |--------|...|--------|...|--------| |
| 77 | // |<--->| |<--->| |
| 78 | // pro epi |
| 79 | if (ARROW_PREDICT_FALSE(length == 0)) { |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | constexpr uint8_t set_byte = value ? UINT8_MAX : 0; |
| 84 | |
| 85 | auto prologue = static_cast<int32_t>(bit_util::RoundUp(offset, 8) - offset); |
| 86 | DCHECK_LT(prologue, 8); |
| 87 | |
| 88 | if (length < prologue) { // special case where a mask is required |
| 89 | // offset length |
| 90 | // data |<->| |
| 91 | // |--------|...|--------|... |
| 92 | // mask --> |111| |
| 93 | // |<---->| |
| 94 | // pro |
| 95 | uint8_t mask = bit_util::kPrecedingBitmask[8 - prologue] ^ |
| 96 | bit_util::kPrecedingBitmask[8 - prologue + length]; |
| 97 | data[offset / 8] = value ? data[offset / 8] | mask : data[offset / 8] & ~mask; |
| 98 | return; |
| 99 | } |
| 100 | |
| 101 | // align to a byte boundary |
| 102 | data[offset / 8] = bit_util::SpliceWord(8 - prologue, data[offset / 8], set_byte); |
| 103 | offset += prologue; |
| 104 | length -= prologue; |
| 105 | |
| 106 | // set values per byte |
| 107 | DCHECK_EQ(offset % 8, 0); |
| 108 | std::memset(data + offset / 8, set_byte, length / 8); |
| 109 | offset += bit_util::RoundDown(length, 8); |
| 110 | length -= bit_util::RoundDown(length, 8); |
| 111 | |
| 112 | // clean up |
| 113 | DCHECK_LT(length, 8); |
| 114 | if (length > 0) { |
| 115 | data[offset / 8] = |
| 116 | bit_util::SpliceWord(static_cast<int32_t>(length), set_byte, data[offset / 8]); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | void SetBitmap(uint8_t* data, int64_t offset, int64_t length) { |
| 121 | SetBitmapImpl<true>(data, offset, length); |
nothing calls this directly
no test coverage detected