| 125 | |
| 126 | template <TransferMode mode> |
| 127 | void TransferBitmap(const uint8_t* data, int64_t offset, int64_t length, |
| 128 | int64_t dest_offset, uint8_t* dest) { |
| 129 | int64_t bit_offset = offset % 8; |
| 130 | int64_t dest_bit_offset = dest_offset % 8; |
| 131 | |
| 132 | if (bit_offset || dest_bit_offset) { |
| 133 | auto reader = internal::BitmapWordReader<uint64_t>(data, offset, length); |
| 134 | auto writer = internal::BitmapWordWriter<uint64_t>(dest, dest_offset, length); |
| 135 | |
| 136 | auto nwords = reader.words(); |
| 137 | while (nwords--) { |
| 138 | auto word = reader.NextWord(); |
| 139 | writer.PutNextWord(mode == TransferMode::Invert ? ~word : word); |
| 140 | } |
| 141 | auto nbytes = reader.trailing_bytes(); |
| 142 | while (nbytes--) { |
| 143 | int valid_bits; |
| 144 | auto byte = reader.NextTrailingByte(valid_bits); |
| 145 | writer.PutNextTrailingByte(mode == TransferMode::Invert ? ~byte : byte, valid_bits); |
| 146 | } |
| 147 | } else if (length) { |
| 148 | int64_t num_bytes = bit_util::BytesForBits(length); |
| 149 | |
| 150 | // Shift by its byte offset |
| 151 | data += offset / 8; |
| 152 | dest += dest_offset / 8; |
| 153 | |
| 154 | // Take care of the trailing bits in the last byte |
| 155 | // E.g., if trailing_bits = 5, last byte should be |
| 156 | // - low 3 bits: new bits from last byte of data buffer |
| 157 | // - high 5 bits: old bits from last byte of dest buffer |
| 158 | int64_t trailing_bits = num_bytes * 8 - length; |
| 159 | uint8_t trail_mask = (1U << (8 - trailing_bits)) - 1; |
| 160 | uint8_t last_data; |
| 161 | |
| 162 | if (mode == TransferMode::Invert) { |
| 163 | for (int64_t i = 0; i < num_bytes - 1; i++) { |
| 164 | dest[i] = static_cast<uint8_t>(~(data[i])); |
| 165 | } |
| 166 | last_data = ~data[num_bytes - 1]; |
| 167 | } else { |
| 168 | std::memcpy(dest, data, static_cast<size_t>(num_bytes - 1)); |
| 169 | last_data = data[num_bytes - 1]; |
| 170 | } |
| 171 | |
| 172 | // Set last byte |
| 173 | dest[num_bytes - 1] &= ~trail_mask; |
| 174 | dest[num_bytes - 1] |= last_data & trail_mask; |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | void ReverseBlockOffsets(const uint8_t* data, int64_t offset, int64_t length, |
| 179 | int64_t dest_offset, uint8_t* dest) { |
nothing calls this directly
no test coverage detected